фиксы новой стратегии
test / deploy_trader_prod (push) Successful in 5m11s Details

dev
vlad zverzhkhovskiy 2025-10-14 14:05:15 +03:00
parent c2612ba85a
commit 022cee9a19
9 changed files with 219 additions and 54 deletions

View File

@ -56,9 +56,10 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
}
public static bool TryCalcTimeWindowsDiff(this ITradeDataItem[] values, TimeSpan boundLeft, TimeSpan boundRight,
Func<ITradeDataItem, decimal> fieldSelector, bool calcMean, out decimal result)
Func<ITradeDataItem, decimal> fieldSelector, bool calcMean, out decimal result, out decimal resultRelative)
{
result = default;
resultRelative = default;
if (values.Length > 1)
{
var shiftTimeR = values.Last().Time - boundRight;
@ -78,6 +79,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
valOld = valOld / valuesOld.Length;
}
result = valNew - valOld;
resultRelative = (valNew - valOld) / valOld;
return true;
}
}

View File

@ -15,10 +15,11 @@
internal const string AreasRelationProcessor = "balancescalc30min";
internal readonly static TimeSpan AreasRelationWindow = TimeSpan.FromMinutes(15);
internal const decimal ForceExecuteCoefficient = 500000m;
internal const decimal PowerUppingCoefficient = 1.69m;
internal const decimal UppingCoefficient = 1.3m;
internal const decimal LowingCoefficient = .76m;
internal const decimal PowerLowingCoefficient = .59m;
internal const decimal BlockingCoefficient = 0m;
internal const decimal BlockingCoefficient = 0.01m;
}
}

View File

@ -0,0 +1,14 @@
using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums;
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
using System.Collections.Immutable;
namespace KLHZ.Trader.Core.Exchange.Models.Trading
{
internal class DeferredDeclision
{
public ImmutableDictionary<TradingEvent, decimal> Events { get; init; } = ImmutableDictionary<TradingEvent, decimal>.Empty;
public Stops Stops { get; init; }
public DateTime ExpirationTime { get; init; }
public required ITradeDataItem Message { get; init; }
}
}

View File

@ -6,5 +6,6 @@
public decimal Pirson { get; init; }
public decimal PriceDiff { get; init; }
public decimal TradesDiff { get; init; }
public decimal TradesDiffRelative { get; init; }
}
}

View File

@ -6,5 +6,6 @@
public decimal LowValue { get; init; }
public decimal HighValue { get; init; }
public DateTime? LastLevelTime { get; init; }
public DateTime CalculatedAt { get; init; }
}
}

View File

@ -34,9 +34,14 @@ namespace KLHZ.Trader.Core.Exchange.Services
private readonly ConcurrentDictionary<string, TradingMode> TradingModes = new();
private readonly ConcurrentDictionary<string, DeferredDeclision> DeferredDeclisions = new();
private readonly ConcurrentDictionary<string, SupportLevel[]> SupportLevels = new();
private readonly ConcurrentDictionary<string, decimal> DPirsonValues = new();
private readonly ConcurrentDictionary<string, decimal> _pirsonValues = new();
private readonly ConcurrentDictionary<string, decimal> _dpirsonValues = new();
private readonly ConcurrentDictionary<string, DateTime> _supportLevelsCalculationTimes = new();
private readonly ConcurrentDictionary<string, DateTime> _usedSupportLevels = new();
private readonly ConcurrentDictionary<string, DateTime> _usedSupportLevelsForClosing = new();
private readonly ConcurrentDictionary<string, ITradeDataItem> _oldItems = new();
private readonly Channel<ITradeDataItem> _pricesChannel = Channel.CreateUnbounded<ITradeDataItem>();
private readonly Channel<ITradeCommand> _commands = Channel.CreateUnbounded<ITradeCommand>();
@ -161,44 +166,109 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
if (message.Figi == "FUTIMOEXF000")
{
if (DeferredDeclisions.TryGetValue(message.Figi, out var dec))
{
if (dec.ExpirationTime < message.Time)
{
if (dec.Events[TradingEvent.OpenShort] > Constants.BlockingCoefficient)
{
if (dec.Message.Price < message.Price)
{
var stops2 = GetStops(message);
var declisionsStops2 = ProcessStops(stops2, 2m);
var e = TraderUtils.MergeResultsMult(dec.Events, declisionsStops2);
await ExecuteDeclisions(e.ToImmutableDictionary(), message, stops2, 1);
}
}
else if (dec.Events[TradingEvent.OpenLong] > Constants.BlockingCoefficient)
{
if (dec.Message.Price > message.Price)
{
var stops2 = GetStops(message);
var declisionsStops2 = ProcessStops(stops2, 2m);
var e = TraderUtils.MergeResultsMult(dec.Events, declisionsStops2);
await ExecuteDeclisions(e.ToImmutableDictionary(), message, stops2, 1);
}
}
else if (dec.Events[TradingEvent.CloseLong] > Constants.BlockingCoefficient
|| dec.Events[TradingEvent.CloseShort] > Constants.BlockingCoefficient)
{
await ExecuteDeclisions(dec.Events, dec.Message, dec.Stops, 1);
}
DeferredDeclisions.TryRemove(message.Figi, out _);
}
}
await CalcSupportLevels(message, 3, 5);
var stops = GetStops(message);
var pirson = await CalcPirson(message);
var declisionPirson = await ProcessPirson(pirson, message);
var declisionsSupportLevels = await ProcessSupportLevels(message);
var declisionsStops = ProcessStops(stops, 1.5m);
var declisionsStops = ProcessStops(stops, 2m);
var res = TraderUtils.MergeResultsMult(declisionPirson, declisionsSupportLevels);
res = TraderUtils.MergeResultsMult(res, declisionsStops);
await ExecuteDeclisions(res.ToImmutableDictionary(), message, stops, 1);
var declision = new DeferredDeclision()
{
Message = message,
Stops = stops,
Events = res.ToImmutableDictionary(),
ExpirationTime = message.Time.AddSeconds(5)
};
if (declision.Events.Values.Any(v => v > Constants.BlockingCoefficient))
{
//DeferredDeclisions.TryAdd(message.Figi, declision);
}
_oldItems[message.Figi] = message;
}
}
private async Task<ImmutableDictionary<TradingEvent, decimal>> ProcessPirson(PirsonCalculatingResult pirson, ITradeDataItem message)
{
var res = TraderUtils.GetInitDict(0);
if (pirson.Success && DPirsonValues.TryGetValue(message.Figi, out var olddpirs))
var res = TraderUtils.GetInitDict(Constants.BlockingCoefficient);
if (pirson.Success && _pirsonValues.TryGetValue(message.Figi, out var olddpirs))
{
if (olddpirs < -0.3m && pirson.Pirson > -0.3m && pirson.PriceDiff > 0 && (pirson.TradesDiff > 0))
var dpirson = pirson.Pirson - olddpirs;
if (olddpirs < 0 && pirson.Pirson > 0 && pirson.PriceDiff > 0 && (pirson.TradesDiffRelative > 0.2m))
{
res[TradingEvent.OpenLong] = Constants.PowerUppingCoefficient;
await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_long_in", message.Price);
}
if (olddpirs > 0.3m && pirson.Pirson < 0.3m && pirson.PriceDiff < 0 && (pirson.TradesDiff > 0))
//if (olddpirs < -0.7m && pirson.Pirson > -0.7m && pirson.PriceDiff > 0 && (pirson.TradesDiffRelative < -0.1m))
//{
// res[TradingEvent.OpenLong] = Constants.PowerUppingCoefficient;
//}
if (olddpirs > 0 && pirson.Pirson < 0 && pirson.PriceDiff < 0 && (pirson.TradesDiffRelative > 0.2m))
{
res[TradingEvent.OpenShort] = Constants.PowerUppingCoefficient;
await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_short_in", message.Price);
}
if (olddpirs > 0.7m && pirson.Pirson < 0.7m)
//if (olddpirs > 0.3m && pirson.Pirson < 0.3m && pirson.PriceDiff < 0 && (pirson.TradesDiffRelative > 0.3m))
//{
// res[TradingEvent.OpenShort] = Constants.PowerUppingCoefficient;
//}
if (_dpirsonValues.TryGetValue(message.Figi, out var oldDprison))
{
// await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_long_out", message.Price);
}
if (olddpirs < -0.7m && pirson.Pirson > -0.7m)
{
// await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_short_out", message.Price);
if (oldDprison > 0.02m && dpirson < -0.02m && pirson.Pirson > 0.7m && pirson.TradesDiffRelative < -0.2m)
{
res[TradingEvent.CloseLong] = Constants.PowerUppingCoefficient;
//await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_long_out", message.Price);
}
if (oldDprison < 0 && dpirson > 0 && pirson.Pirson < -0.6m && pirson.TradesDiffRelative < -0.1m)
{
res[TradingEvent.CloseShort] = Constants.PowerUppingCoefficient;
// await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_short_out", message.Price);
}
}
_dpirsonValues[message.Figi] = dpirson;
}
DPirsonValues[message.Figi] = pirson.Pirson;
_pirsonValues[message.Figi] = pirson.Pirson;
return res.ToImmutableDictionary();
}
@ -212,7 +282,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
var buys = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, cacheSize, selector: (i) => i.Direction == 1);
var trades = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, cacheSize);
if (trades.TryCalcTimeWindowsDiff(bigWindow, smallWindow, v => v.Count, false, out var tradesDiff)
if (trades.TryCalcTimeWindowsDiff(bigWindow, smallWindow, v => v.Count, false, out var tradesDiff, out var tradesDiffRelative)
&& buys.TryCalcTimeDiff(bigWindow, smallWindow, v => v.Price, true, out var pricesDiff))
{
await _tradeDataProvider.LogPrice(message, "privcesDiff", pricesDiff);
@ -243,6 +313,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
Pirson = res,
PriceDiff = pricesDiff,
TradesDiff = tradesDiff,
TradesDiffRelative = tradesDiffRelative,
Success = true,
};
}
@ -276,10 +347,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
var data = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, TimeSpan.FromHours(depthHours));
if (data.Length > 0)
{
if (data[^1].Time - data[0].Time < TimeSpan.FromHours(depthHours - 1))
if (data[^1].Time - data[0].Time < TimeSpan.FromHours(0.5))
{
data = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, TimeSpan.FromHours(depthHours + 12));
if (data[^1].Time - data[0].Time < TimeSpan.FromHours(depthHours - 1))
if (data[^1].Time - data[0].Time < TimeSpan.FromHours(0.5))
{
return;
}
@ -305,6 +376,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
HighValue = high,
LowValue = low,
Value = c.Value,
CalculatedAt = message.Time,
});
}
else if (last.HighValue >= low && last.HighValue < high)
@ -313,7 +385,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
LowValue = last.LowValue,
HighValue = high,
Value = last.LowValue + (high - last.LowValue) / 2
Value = last.LowValue + (high - last.LowValue) / 2,
CalculatedAt = message.Time,
};
}
}
@ -324,6 +397,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
HighValue = high,
LowValue = low,
Value = c.Value,
CalculatedAt = message.Time,
});
}
}
@ -346,6 +420,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
LowValue = level.LowValue,
Value = level.Value,
LastLevelTime = time,
CalculatedAt = message.Time,
};
i++;
}
@ -426,7 +501,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
var sign = positionType == PositionType.Long ? 1 : 1;
foreach (var acc in accounts)
{
if (TraderUtils.IsOperationAllowed(acc, message.Price, 1, _exchangeConfig.AccountCashPartFutures, _exchangeConfig.AccountCashPart))
if (TraderUtils.IsOperationAllowed(acc, message.Price, count, _exchangeConfig.AccountCashPartFutures, _exchangeConfig.AccountCashPart))
{
await acc.OpenPosition(message.Figi, positionType, stopLossShift, takeProfitShift, count);
await _dataBus.Broadcast(new MessageForAdmin()
@ -448,7 +523,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
private async Task ExecuteDeclisions(ImmutableDictionary<TradingEvent, decimal> result, ITradeDataItem message, Stops st, int accountsForOpening = 1)
{
var state = ExchangeScheduler.GetCurrentState();
var state = ExchangeScheduler.GetCurrentState(message.Time);
if (result[TradingEvent.OpenLong] >= Constants.UppingCoefficient
&& state == ExchangeState.Open
)
@ -464,15 +539,18 @@ namespace KLHZ.Trader.Core.Exchange.Services
.ToArray();
await OpenPositions(accounts, message, PositionType.Long, stops.stopLoss, stops.takeProfit, 1);
}
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.OpenLong, message.Price, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(-100, 100)), message);
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, message.Price + stops.takeProfit, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message);
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, message.Price - stops.stopLoss, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message);
var val = message.Price;
var valLow = message.Price - stops.stopLoss;
var valHigh = message.Price + stops.takeProfit;
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.OpenLong, val, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(-100, 100)), message);
//await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, valHigh, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message);
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, valLow, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message);
}
if (result[TradingEvent.OpenShort] >= Constants.UppingCoefficient
&& state == ExchangeState.Open
)
{
var stops = st.GetStops(PositionType.Long);
var stops = st.GetStops(PositionType.Short);
if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase())
{
var accounts = _portfolioWrapper.Accounts
@ -482,12 +560,14 @@ namespace KLHZ.Trader.Core.Exchange.Services
.ToArray();
await OpenPositions(accounts, message, PositionType.Short, stops.stopLoss, stops.takeProfit, 1);
}
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.OpenShort, message.Price, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(-100, 100)), message);
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsShort, message.Price - stops.takeProfit, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message);
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsShort, message.Price + stops.stopLoss, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message);
var val = message.Price;
var valLow = message.Price - stops.takeProfit;
var valHigh = message.Price + stops.stopLoss;
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.OpenShort, val, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(-100, 100)), message);
//await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsShort, valLow, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message);
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsShort, valHigh, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message);
}
if (result[TradingEvent.CloseLong] >= Constants.UppingCoefficient * 10)
if (result[TradingEvent.CloseLong] >= Constants.UppingCoefficient)
{
if (!message.IsHistoricalData && BotModeSwitcher.CanSell())
{
@ -501,7 +581,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
}
if (result[TradingEvent.CloseShort] >= Constants.UppingCoefficient * 10)
if (result[TradingEvent.CloseShort] >= Constants.UppingCoefficient)
{
if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase())
{
@ -550,10 +630,11 @@ namespace KLHZ.Trader.Core.Exchange.Services
private Stops GetStops(ITradeDataItem message)
{
decimal longStopLossShift = message.Value * 0.99m;
decimal longTakeProfitShift = message.Value * 1.03m;
decimal shortStopLossShift = message.Value * 0.99m;
decimal shortTakeProfitShift = message.Value * 1.03m;
var additionalShift = message.Price * 0.001m;
var longStopLossShift = message.Price * 0.0025m;
var longTakeProfitShift = message.Price * 0.02m;
var shortStopLossShift = message.Price * 0.0025m;
var shortTakeProfitShift = message.Price * 0.02m;
if (SupportLevels.TryGetValue(message.Figi, out var levels))
{
if (levels.Length > 0)
@ -564,16 +645,29 @@ namespace KLHZ.Trader.Core.Exchange.Services
if (message.Price >= levelsByTime[0].LowValue && message.Price < levelsByTime[0].HighValue)
{
longStopLossShift = message.Price - levelsByTime[0].LowValue;
shortStopLossShift = message.Price + levelsByTime[0].HighValue;
shortStopLossShift = levelsByTime[0].HighValue - message.Price;
}
else
{
var levelsByDiff = levels.Where(l => l.LastLevelTime.HasValue)
.OrderBy(l => System.Math.Abs(l.Value - message.Price))
var levelsByDiffForLong = levels.Where(l => l.LastLevelTime.HasValue)
.OrderBy(l => l.Value - message.Price)
.ToArray();
var nearestLevel = levelsByDiff[0];
longStopLossShift = message.Price - nearestLevel.HighValue;
shortStopLossShift = nearestLevel.LowValue - message.Price;
var levelsByDiffForShort = levels.Where(l => l.LastLevelTime.HasValue)
.OrderByDescending(l => l.Value - message.Price)
.ToArray();
var nearestLevel = levelsByDiffForLong[0];
if (message.Price > nearestLevel.HighValue)
{
longStopLossShift = message.Price - nearestLevel.HighValue + additionalShift;
}
nearestLevel = levelsByDiffForShort[0];
if (message.Price < nearestLevel.LowValue)
{
shortStopLossShift = nearestLevel.LowValue - message.Price + additionalShift;
}
}
}
}
@ -613,17 +707,69 @@ namespace KLHZ.Trader.Core.Exchange.Services
var levelsByTime = levels.Where(l => l.LastLevelTime.HasValue)
.OrderByDescending(l => l.LastLevelTime)
.ToArray();
if (message.Price >= levelsByTime[0].LowValue && message.Price < levelsByTime[0].HighValue)
var levelByTime = levelsByTime[0];
if (message.Price >= levelByTime.LowValue && message.Price < levelByTime.HighValue)
{
if (message.Price > levelsByTime[0].Value)
if (message.Price > levelByTime.Value)
{
res[TradingEvent.OpenLong] = Constants.BlockingCoefficient;
}
if (message.Price < levelsByTime[0].Value)
if (message.Price < levelByTime.Value)
{
res[TradingEvent.OpenShort] = Constants.BlockingCoefficient;
}
if (_oldItems.TryGetValue(message.Figi, out var old1))
{
var islevelUsed = false;
if (_usedSupportLevelsForClosing.TryGetValue(message.Figi, out var time))
{
if (time == levelByTime.CalculatedAt)
{
islevelUsed = true;
}
}
if (!islevelUsed)
{
if (old1.Price < levelByTime.LowValue || levelByTime.CalculatedAt == message.Time)
{
res[TradingEvent.CloseLong] = Constants.ForceExecuteCoefficient;
_usedSupportLevelsForClosing[message.Figi] = levelByTime.CalculatedAt;
}
if (old1.Price > levelByTime.HighValue || levelByTime.CalculatedAt == message.Time)
{
res[TradingEvent.CloseShort] = Constants.ForceExecuteCoefficient;
_usedSupportLevelsForClosing[message.Figi] = levelByTime.CalculatedAt;
}
}
}
}
else if (_oldItems.TryGetValue(message.Figi, out var old))
{
if (old.Price >= levelByTime.LowValue && old.Price < levelByTime.HighValue)
{
var islevelUsed = false;
if (_usedSupportLevels.TryGetValue(message.Figi, out var time))
{
if (time == levelByTime.CalculatedAt)
{
islevelUsed = true;
}
}
if (!islevelUsed)
{
if (message.Price < levelByTime.LowValue)
{
res[TradingEvent.OpenShort] = Constants.ForceExecuteCoefficient;
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
}
else if (message.Price > levelByTime.HighValue)
{
res[TradingEvent.OpenLong] = Constants.ForceExecuteCoefficient;
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
}
}
}
}
}
}

View File

@ -24,6 +24,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
private readonly IDbContextFactory<TraderDbContext> _dbContextFactory;
private readonly ILogger<TraderDataProvider> _logger;
private readonly string[] _instrumentsFigis = [];
private readonly string[] _tradingInstrumentsFigis = [];
public readonly ConcurrentDictionary<string, IOrderbook> Orderbooks = new();
private readonly ConcurrentDictionary<string, string> _tickersCache = new();
@ -40,6 +41,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
_dbContextFactory = dbContextFactory;
_logger = logger;
_instrumentsFigis = options.Value.DataRecievingInstrumentsFigis.ToArray();
_tradingInstrumentsFigis = options.Value.TradingInstrumentsFigis.ToArray();
_isDataRecievingAllowed = options.Value.ExchangeDataRecievingEnabled;
}
@ -142,11 +144,11 @@ namespace KLHZ.Trader.Core.Exchange.Services
if (_isDataRecievingAllowed)
{
var time = DateTime.UtcNow.AddHours(-5);
var time = DateTime.UtcNow.AddHours(-20);
using var context1 = await _dbContextFactory.CreateDbContextAsync();
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var data = await context1.PriceChanges
.Where(c => _instrumentsFigis.Contains(c.Figi) && c.Time >= time)
.Where(c => _tradingInstrumentsFigis.Contains(c.Figi) && c.Time >= time)
.OrderBy(c => c.Time)
.Select(c => new TradeDataItem()
{
@ -262,6 +264,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
Action = action,
}, false);
}
private async Task WritePricesTask()
{
var buffer1 = new List<ProcessedPrice>();

View File

@ -23,10 +23,7 @@ namespace KLHZ.Trader.Core.Exchange.Utils
var time = TimeOnly.FromDateTime(dt);
if (day == DayOfWeek.Sunday || day == DayOfWeek.Saturday)
{
if (time > _openTimeHoliday && time < _closeTimeHoliday)
{
return ExchangeState.Open;
}
return ExchangeState.Close;
}
else
{

View File

@ -12,7 +12,7 @@
"Token": "",
"ManagingAccountNamePatterns": [ "автотрейд" ],
"DataRecievingInstrumentsFigis": [ "BBG004730N88", "FUTIMOEXF000", "FUTGMKN09250", "FUTBR1025000", "FUTNG0925000", "FUTNASD09250" ],
"TradingInstrumentsFigis": [ "FUTIMOEXF000", "BBG004730N88" ],
"TradingInstrumentsFigis": [ "FUTIMOEXF000"],
"FutureComission": 0.0025,
"ShareComission": 0.0004,
"AccountCashPart": 0.05,