Compare commits
No commits in common. "c3c6b52b7b10611550f18410843bb9dd3b6eb6bc" and "941e00e3466cbae65028c584a93076275f293a69" have entirely different histories.
c3c6b52b7b
...
941e00e346
|
@ -125,85 +125,5 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||||||
}
|
}
|
||||||
return (res, bigWindowAv, smallWindowAv);
|
return (res, bigWindowAv, smallWindowAv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (TradingEvent events, decimal bigWindowAv, decimal smallWindowAv) CheckByWindowAverageMean2(DateTime[] timestamps,
|
|
||||||
decimal[] prices, int size, int smallWindow, int bigWindow, TimeSpan timeForUptreandStart,
|
|
||||||
decimal uptrendStartingDetectionMeanfullStep = 0m, decimal uptrendEndingDetectionMeanfullStep = 3m)
|
|
||||||
{
|
|
||||||
var res = TradingEvent.None;
|
|
||||||
var bigWindowAv = 0m;
|
|
||||||
var smallWindowAv = 0m;
|
|
||||||
var s = 0;
|
|
||||||
var pricesForFinalComparison = new decimal[size];
|
|
||||||
var twavss = new decimal[size];
|
|
||||||
var twavbs = new decimal[size];
|
|
||||||
var times = new DateTime[size];
|
|
||||||
var crossings = new List<int>();
|
|
||||||
for (int shift = 0; shift < size - 1 && shift < prices.Length - 1; shift++)
|
|
||||||
{
|
|
||||||
s = shift;
|
|
||||||
var i2 = size - 1 - shift;
|
|
||||||
var i1 = size - 2 - shift;
|
|
||||||
|
|
||||||
var twavs = CalcTimeWindowAverageValue(timestamps, prices, smallWindow, shift);
|
|
||||||
var twavb = CalcTimeWindowAverageValue(timestamps, prices, bigWindow, shift);
|
|
||||||
pricesForFinalComparison[i2] = prices[prices.Length - 1 - shift];
|
|
||||||
|
|
||||||
if (shift == 0)
|
|
||||||
{
|
|
||||||
bigWindowAv = twavb.value;
|
|
||||||
smallWindowAv = twavs.value;
|
|
||||||
}
|
|
||||||
twavss[i2] = twavs.value;
|
|
||||||
twavbs[i2] = twavb.value;
|
|
||||||
times[i2] = twavb.time;
|
|
||||||
|
|
||||||
if (shift > 0)
|
|
||||||
{
|
|
||||||
var isCrossing = Lines.IsLinesCrossing(
|
|
||||||
times[i1 + 1],
|
|
||||||
times[i2 + 1],
|
|
||||||
twavss[i1 + 1],
|
|
||||||
twavss[i2 + 1],
|
|
||||||
twavbs[i1 + 1],
|
|
||||||
twavbs[i2 + 1]);
|
|
||||||
|
|
||||||
if (shift == 1 && !isCrossing.res) //если нет пересечения скользящих средний с окном 120 и 15 секунд между
|
|
||||||
//текущей и предыдущей точкой - можно не продолжать выполнение.
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCrossing.res)
|
|
||||||
{
|
|
||||||
crossings.Add(i2);
|
|
||||||
if (crossings.Count == 2)
|
|
||||||
{
|
|
||||||
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
|
|
||||||
if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2])
|
|
||||||
{
|
|
||||||
if (pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]] >= uptrendEndingDetectionMeanfullStep
|
|
||||||
&& times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart)
|
|
||||||
{
|
|
||||||
res |= TradingEvent.UptrendEnd;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта
|
|
||||||
if (twavss[size - 1] >= twavbs[size - 1] && twavss[size - 2] < twavbs[size - 2])
|
|
||||||
{
|
|
||||||
if (pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]] <= uptrendStartingDetectionMeanfullStep
|
|
||||||
&& times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart)
|
|
||||||
{
|
|
||||||
res |= TradingEvent.UptrendStart;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (res, bigWindowAv, smallWindowAv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ using System.Collections.Concurrent;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using Tinkoff.InvestApi;
|
using Tinkoff.InvestApi;
|
||||||
|
using Tinkoff.InvestApi.V1;
|
||||||
using AssetType = KLHZ.Trader.Core.Exchange.Models.AssetsAccounting.AssetType;
|
using AssetType = KLHZ.Trader.Core.Exchange.Models.AssetsAccounting.AssetType;
|
||||||
|
|
||||||
namespace KLHZ.Trader.Core.Exchange.Services
|
namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
|
@ -42,6 +43,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
private readonly decimal _accountCashPart;
|
private readonly decimal _accountCashPart;
|
||||||
private readonly decimal _accountCashPartFutures;
|
private readonly decimal _accountCashPartFutures;
|
||||||
private readonly string[] _tradingInstrumentsFigis = [];
|
private readonly string[] _tradingInstrumentsFigis = [];
|
||||||
|
private readonly bool _isDebug = false;
|
||||||
private readonly Channel<INewPrice> _pricesChannel = Channel.CreateUnbounded<INewPrice>();
|
private readonly Channel<INewPrice> _pricesChannel = Channel.CreateUnbounded<INewPrice>();
|
||||||
private readonly Channel<IOrderbook> _ordersbookChannel = Channel.CreateUnbounded<IOrderbook>();
|
private readonly Channel<IOrderbook> _ordersbookChannel = Channel.CreateUnbounded<IOrderbook>();
|
||||||
|
|
||||||
|
@ -60,6 +62,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
_accountCashPart = options.Value.AccountCashPart;
|
_accountCashPart = options.Value.AccountCashPart;
|
||||||
_accountCashPartFutures = options.Value.AccountCashPartFutures;
|
_accountCashPartFutures = options.Value.AccountCashPartFutures;
|
||||||
_tradingInstrumentsFigis = options.Value.TradingInstrumentsFigis;
|
_tradingInstrumentsFigis = options.Value.TradingInstrumentsFigis;
|
||||||
|
_isDebug = !options.Value.ExchangeDataRecievingEnabled;
|
||||||
foreach (var f in _tradingInstrumentsFigis)
|
foreach (var f in _tradingInstrumentsFigis)
|
||||||
{
|
{
|
||||||
TradingModes[f] = TradingMode.None;
|
TradingModes[f] = TradingMode.None;
|
||||||
|
@ -78,6 +81,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
_dataBus.AddChannel(nameof(Trader), _ordersbookChannel);
|
_dataBus.AddChannel(nameof(Trader), _ordersbookChannel);
|
||||||
_ = ProcessPrices();
|
_ = ProcessPrices();
|
||||||
_ = ProcessOrders();
|
_ = ProcessOrders();
|
||||||
|
if (!_isDebug)
|
||||||
|
{
|
||||||
|
_ = TradingModeUpdatingWorker();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<(DateTime[] timestamps, decimal[] prices, bool isFullIntervalExists)> GetData(INewPrice message)
|
public async ValueTask<(DateTime[] timestamps, decimal[] prices, bool isFullIntervalExists)> GetData(INewPrice message)
|
||||||
|
@ -165,27 +172,27 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
};
|
};
|
||||||
list.Clear();
|
list.Clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
|
||||||
if (timesCache.TryGetValue(message.Figi, out var dt))
|
|
||||||
{
|
{
|
||||||
if ((message.Time - dt).TotalSeconds > 10)
|
if (timesCache.TryGetValue(message.Figi, out var dt))
|
||||||
|
{
|
||||||
|
if ((message.Time - dt).TotalSeconds > 120)
|
||||||
|
{
|
||||||
|
timesCache[message.Figi] = message.Time;
|
||||||
|
|
||||||
|
TradingModes[message.Figi] = await CalcTradingMode(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
timesCache[message.Figi] = message.Time;
|
timesCache[message.Figi] = message.Time;
|
||||||
|
|
||||||
TradingModes[message.Figi] = await CalcTradingMode(message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
timesCache[message.Figi] = message.Time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (TradingModes.TryGetValue(message.Figi, out var mode))
|
if (TradingModes.TryGetValue(message.Figi, out var mode))
|
||||||
{
|
{
|
||||||
|
@ -243,16 +250,12 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
}
|
}
|
||||||
else if (TradingModes[message.Figi] == TradingMode.SlowDropping)
|
else if (TradingModes[message.Figi] == TradingMode.SlowDropping)
|
||||||
{
|
{
|
||||||
await ProcessNewPriceIMOEXF_Dropping(data, state, message, windowMaxSize, 2);
|
await ProcessNewPriceIMOEXF_Dropping(data, state, message, windowMaxSize, 3);
|
||||||
}
|
}
|
||||||
else if (TradingModes[message.Figi] == TradingMode.Dropping)
|
else if (TradingModes[message.Figi] == TradingMode.Dropping)
|
||||||
{
|
{
|
||||||
await ProcessNewPriceIMOEXF_Dropping(data, state, message, windowMaxSize, 6);
|
await ProcessNewPriceIMOEXF_Dropping(data, state, message, windowMaxSize, 6);
|
||||||
}
|
}
|
||||||
else if (TradingModes[message.Figi] == TradingMode.Growing)
|
|
||||||
{
|
|
||||||
await ProcessNewPriceIMOEXF_Growing(data, state, message, windowMaxSize);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await ProcessNewPriceIMOEXF2(data, state, message, windowMaxSize);
|
await ProcessNewPriceIMOEXF2(data, state, message, windowMaxSize);
|
||||||
|
@ -264,7 +267,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -364,19 +367,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
return resultMoveAvFull.events;
|
return resultMoveAvFull.events;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<TradingEvent> CheckByWindowAverageMean2((DateTime[] timestamps, decimal[] prices) data, int smallWindow, int bigWindow,
|
|
||||||
INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullStep = 0m, decimal uptrendEndingDetectionMeanfullStep = 3m)
|
|
||||||
{
|
|
||||||
var resultMoveAvFull = MovingAverage.CheckByWindowAverageMean2(data.timestamps, data.prices,
|
|
||||||
windowMaxSize, smallWindow, bigWindow, TimeSpan.FromSeconds(20), uptrendStartingDetectionMeanfullStep, uptrendEndingDetectionMeanfullStep);
|
|
||||||
if (resultMoveAvFull.bigWindowAv != 0)
|
|
||||||
{
|
|
||||||
await LogPrice(message, Constants.BigWindowCrossingAverageProcessor, resultMoveAvFull.bigWindowAv);
|
|
||||||
await LogPrice(message, Constants.SmallWindowCrossingAverageProcessor, resultMoveAvFull.smallWindowAv);
|
|
||||||
}
|
|
||||||
return resultMoveAvFull.events;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task<TradingEvent> CheckByWindowAverageMeanNolog((DateTime[] timestamps, decimal[] prices) data,
|
private Task<TradingEvent> CheckByWindowAverageMeanNolog((DateTime[] timestamps, decimal[] prices) data,
|
||||||
INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullStep = 0m, decimal uptrendEndingDetectionMeanfullStep = 3m)
|
INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullStep = 0m, decimal uptrendEndingDetectionMeanfullStep = 3m)
|
||||||
{
|
{
|
||||||
|
@ -458,7 +448,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
var sells = sberSells.Sum(s => s.Value);
|
var sells = sberSells.Sum(s => s.Value);
|
||||||
var buys = sberBuys.Sum(s => s.Value);
|
var buys = sberBuys.Sum(s => s.Value);
|
||||||
var su = sells + buys;
|
var su = sells + buys;
|
||||||
if (su != 0)
|
if (su!=0)
|
||||||
{
|
{
|
||||||
var dsell = (sells / su - 0.5m) * 2;
|
var dsell = (sells / su - 0.5m) * 2;
|
||||||
}
|
}
|
||||||
|
@ -482,8 +472,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart
|
if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart
|
||||||
&& !LongOpeningStops.ContainsKey(message.Figi)
|
&& !LongOpeningStops.ContainsKey(message.Figi)
|
||||||
&& trendTask.Result.HasValue
|
&& trendTask.Result.HasValue
|
||||||
|
&& trendTask.Result.Value > -5
|
||||||
&& state == ExchangeState.Open
|
&& state == ExchangeState.Open
|
||||||
&& areasTask.Result.HasValue
|
&& areasTask.Result.HasValue
|
||||||
|
&& (areasTask.Result.Value >= 20 && areasTask.Result.Value < 75)
|
||||||
&& (positionTask.Result == ValueAmplitudePosition.LowerThenMediana)
|
&& (positionTask.Result == ValueAmplitudePosition.LowerThenMediana)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -637,18 +629,20 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
ExchangeState state,
|
ExchangeState state,
|
||||||
INewPrice message, int windowMaxSize)
|
INewPrice message, int windowMaxSize)
|
||||||
{
|
{
|
||||||
if (data.timestamps.Length <= 4 || state != ExchangeState.Open)
|
if (data.timestamps.Length <= 4 || state!=ExchangeState.Open)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mavTask = CheckByWindowAverageMean2(data, 30, 180, message, windowMaxSize, 0, 0);
|
var mavTask = CheckByWindowAverageMean(data, message, windowMaxSize, -1, 1m);
|
||||||
|
var ltTask = CheckByLocalTrends(data, message, windowMaxSize);
|
||||||
|
var positionTask = CheckPosition(message);
|
||||||
|
|
||||||
await Task.WhenAll(mavTask);
|
await Task.WhenAll(mavTask, ltTask, positionTask);
|
||||||
var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi);
|
var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi);
|
||||||
var res = mavTask.Result;
|
var res = mavTask.Result | ltTask.Result;
|
||||||
|
|
||||||
if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart)
|
if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart && (positionTask.Result == ValueAmplitudePosition.None || positionTask.Result == ValueAmplitudePosition.LowerThenMediana))
|
||||||
{
|
{
|
||||||
if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase())
|
if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase())
|
||||||
{
|
{
|
||||||
|
@ -660,7 +654,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
{
|
{
|
||||||
if (IsBuyAllowed(acc.Value, message.Value, 1, _accountCashPartFutures, _accountCashPart))
|
if (IsBuyAllowed(acc.Value, message.Value, 1, _accountCashPartFutures, _accountCashPart))
|
||||||
{
|
{
|
||||||
if (await acc.Value.Lock(TimeSpan.FromSeconds(30)))
|
if (RandomNumberGenerator.GetInt32(100) > 50 && await acc.Value.Lock(TimeSpan.FromSeconds(12)))
|
||||||
{
|
{
|
||||||
var command = new TradeCommand()
|
var command = new TradeCommand()
|
||||||
{
|
{
|
||||||
|
@ -704,7 +698,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
Figi = message.Figi,
|
Figi = message.Figi,
|
||||||
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.LimitSell,
|
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.LimitSell,
|
||||||
Count = (long)asset.Count,
|
Count = (long)asset.Count,
|
||||||
RecomendPrice = asset.BoughtPrice + 1.5m,
|
RecomendPrice = asset.BoughtPrice + 3,
|
||||||
EnableMargin = false,
|
EnableMargin = false,
|
||||||
};
|
};
|
||||||
await _dataBus.Broadcast(command);
|
await _dataBus.Broadcast(command);
|
||||||
|
@ -714,133 +708,23 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessNewPriceIMOEXF_Growing(
|
|
||||||
(DateTime[] timestamps, decimal[] prices) data,
|
|
||||||
ExchangeState state,
|
|
||||||
INewPrice message, int windowMaxSize)
|
|
||||||
{
|
|
||||||
if (data.timestamps.Length <= 4 || state != ExchangeState.Open)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mavTask = CheckByWindowAverageMean2(data, 30, 180, message, windowMaxSize, 0, 0);
|
|
||||||
|
|
||||||
await Task.WhenAll(mavTask);
|
|
||||||
var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi);
|
|
||||||
var res = mavTask.Result;
|
|
||||||
|
|
||||||
if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart)
|
|
||||||
{
|
|
||||||
if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase())
|
|
||||||
{
|
|
||||||
var accounts = _tradeDataProvider.Accounts
|
|
||||||
.Where(a => !a.Value.Assets.ContainsKey(message.Figi))
|
|
||||||
.ToArray();
|
|
||||||
var loggedDeclisions = 0;
|
|
||||||
foreach (var acc in accounts)
|
|
||||||
{
|
|
||||||
if (IsBuyAllowed(acc.Value, message.Value, 1, _accountCashPartFutures, _accountCashPart))
|
|
||||||
{
|
|
||||||
if (RandomNumberGenerator.GetInt32(100) > 50 && await acc.Value.Lock(TimeSpan.FromSeconds(12)))
|
|
||||||
{
|
|
||||||
var command = new TradeCommand()
|
|
||||||
{
|
|
||||||
AccountId = acc.Value.AccountId,
|
|
||||||
Figi = message.Figi,
|
|
||||||
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.LimitBuy,
|
|
||||||
Count = 1,
|
|
||||||
RecomendPrice = message.Value - 0.5m,
|
|
||||||
ExchangeObject = acc.Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
await _dataBus.Broadcast(command);
|
|
||||||
_logger.LogWarning("Выставлена заявка на покупку актива {figi}! id команды {commandId}. Направление сделки: {dir}; Количество активов: {count}; Разрешена ли маржиналка: {margin}",
|
|
||||||
message.Figi, command.CommandId, command.CommandType, command.Count, command.EnableMargin);
|
|
||||||
if (loggedDeclisions == 0)
|
|
||||||
{
|
|
||||||
await LogDeclision(DeclisionTradeAction.OpenLongReal, message);
|
|
||||||
LongOpeningStops[message.Figi] = message.Time.AddMinutes(1);
|
|
||||||
loggedDeclisions++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await LogDeclision(DeclisionTradeAction.OpenLong, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
|
|
||||||
{
|
|
||||||
if (!message.IsHistoricalData && BotModeSwitcher.CanSell())
|
|
||||||
{
|
|
||||||
var loggedDeclisions = 0;
|
|
||||||
var assetsForClose = _tradeDataProvider.Accounts
|
|
||||||
.SelectMany(a => a.Value.Assets.Values)
|
|
||||||
.Where(a => a.Figi == message.Figi && a.Count > 0)
|
|
||||||
.ToArray();
|
|
||||||
foreach (var asset in assetsForClose)
|
|
||||||
{
|
|
||||||
if (await asset.Lock(TimeSpan.FromSeconds(60)))
|
|
||||||
{
|
|
||||||
var profit = 0m;
|
|
||||||
|
|
||||||
if (assetType == AssetType.Common && asset.Count > 0)
|
|
||||||
{
|
|
||||||
profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value,
|
|
||||||
GetComission(assetType), 1, false);
|
|
||||||
}
|
|
||||||
if (assetType == AssetType.Futures)
|
|
||||||
{
|
|
||||||
profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value,
|
|
||||||
GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profit > 0)
|
|
||||||
{
|
|
||||||
LongClosingStops[message.Figi] = message.Time.AddSeconds(30);
|
|
||||||
var command = new TradeCommand()
|
|
||||||
{
|
|
||||||
AccountId = asset.AccountId,
|
|
||||||
Figi = message.Figi,
|
|
||||||
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketSell,
|
|
||||||
Count = (long)asset.Count,
|
|
||||||
RecomendPrice = null,
|
|
||||||
EnableMargin = false,
|
|
||||||
};
|
|
||||||
await _dataBus.Broadcast(command);
|
|
||||||
_logger.LogWarning("Продажа актива {figi}! id команды {commandId}. Направление сделки: {dir}; Количество активов: {count}; Разрешена ли маржиналка: {margin}",
|
|
||||||
message.Figi, command.CommandId, command.CommandType, command.Count, command.EnableMargin);
|
|
||||||
if (loggedDeclisions == 0)
|
|
||||||
{
|
|
||||||
loggedDeclisions++;
|
|
||||||
await LogDeclision(DeclisionTradeAction.CloseLongReal, message, profit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await LogDeclision(DeclisionTradeAction.CloseLong, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ProcessNewPriceIMOEXF_Dropping(
|
private async Task ProcessNewPriceIMOEXF_Dropping(
|
||||||
(DateTime[] timestamps, decimal[] prices) data,
|
(DateTime[] timestamps, decimal[] prices) data,
|
||||||
ExchangeState state,
|
ExchangeState state,
|
||||||
INewPrice message, int windowMaxSize, decimal step)
|
INewPrice message, int windowMaxSize, decimal step)
|
||||||
{
|
{
|
||||||
if (data.timestamps.Length <= 4 && state != ExchangeState.Open)
|
if (data.timestamps.Length <= 4 && state !=ExchangeState.Open)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mavTask = CheckByWindowAverageMean2(data, 30, 180, message, windowMaxSize, 0, 0);
|
var mavTask = CheckByWindowAverageMean(data, message, windowMaxSize, -1, 1m);
|
||||||
|
var ltTask = CheckByLocalTrends(data, message, windowMaxSize);
|
||||||
var positionTask = CheckPosition(message);
|
var positionTask = CheckPosition(message);
|
||||||
|
|
||||||
await Task.WhenAll(mavTask, positionTask);
|
await Task.WhenAll(mavTask, ltTask, positionTask);
|
||||||
var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi);
|
var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi);
|
||||||
var res = mavTask.Result;
|
var res = mavTask.Result | ltTask.Result;
|
||||||
|
|
||||||
if ((res & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd && (positionTask.Result != ValueAmplitudePosition.LowerThenMediana))
|
if ((res & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd && (positionTask.Result != ValueAmplitudePosition.LowerThenMediana))
|
||||||
{
|
{
|
||||||
|
@ -862,7 +746,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
Figi = message.Figi,
|
Figi = message.Figi,
|
||||||
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketSell,
|
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketSell,
|
||||||
Count = 1,
|
Count = 1,
|
||||||
RecomendPrice = message.Value - 0.5m,
|
RecomendPrice = message.Value,
|
||||||
ExchangeObject = acc.Value,
|
ExchangeObject = acc.Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1064,9 +948,9 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
if (largeData.isFullIntervalExists && smallData.isFullIntervalExists)
|
if (largeData.isFullIntervalExists && smallData.isFullIntervalExists)
|
||||||
{
|
{
|
||||||
if (LocalTrends.TryCalcTrendDiff(largeData.timestamps, largeData.prices, out var largeDataRes)
|
if (LocalTrends.TryCalcTrendDiff(largeData.timestamps, largeData.prices, out var largeDataRes)
|
||||||
&& LocalTrends.TryCalcTrendDiff(smallData.timestamps, smallData.prices, out var smallDataRes))
|
&& LocalTrends.TryCalcTrendDiff(smallData.timestamps, smallData.prices, out var smallDataRes))
|
||||||
{
|
{
|
||||||
if (largeDataRes > 0 && largeDataRes <= 4 && System.Math.Abs(smallDataRes) < 3)
|
if (largeDataRes>0 && largeDataRes <= 4 && System.Math.Abs(smallDataRes)<3)
|
||||||
{
|
{
|
||||||
res = TradingMode.Stable;
|
res = TradingMode.Stable;
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +958,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
{
|
{
|
||||||
res = TradingMode.SlowDropping;
|
res = TradingMode.SlowDropping;
|
||||||
}
|
}
|
||||||
if (largeDataRes > 5 && smallDataRes > 0)
|
if (largeDataRes>5 && smallDataRes > 0)
|
||||||
{
|
{
|
||||||
res = TradingMode.Growing;
|
res = TradingMode.Growing;
|
||||||
}
|
}
|
||||||
|
@ -1094,6 +978,24 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task TradingModeUpdatingWorker()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var figi in _tradingInstrumentsFigis)
|
||||||
|
{
|
||||||
|
TradingModes[figi] = await CalcTradingMode(figi);
|
||||||
|
}
|
||||||
|
await Task.Delay(120000);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Ошибка при вычислении режима торговли.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
internal static bool IsBuyAllowed(ManagedAccount account, decimal boutPrice, decimal count,
|
internal static bool IsBuyAllowed(ManagedAccount account, decimal boutPrice, decimal count,
|
||||||
decimal accountCashPartFutures, decimal accountCashPart)
|
decimal accountCashPartFutures, decimal accountCashPart)
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,7 +98,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
|
|
||||||
public async ValueTask AddData(INewPrice message, TimeSpan? clearingInterval = null)
|
public async ValueTask AddData(INewPrice message, TimeSpan? clearingInterval = null)
|
||||||
{
|
{
|
||||||
if (message.Direction != 1) return;
|
|
||||||
if (_historyCash.TryGetValue(message.Figi, out var unit))
|
if (_historyCash.TryGetValue(message.Figi, out var unit))
|
||||||
{
|
{
|
||||||
if (clearingInterval.HasValue)
|
if (clearingInterval.HasValue)
|
||||||
|
@ -216,9 +215,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
Ticker = c.Ticker,
|
Ticker = c.Ticker,
|
||||||
Time = c.Time,
|
Time = c.Time,
|
||||||
Value = c.Value,
|
Value = c.Value,
|
||||||
IsHistoricalData = true,
|
IsHistoricalData = true
|
||||||
Direction = c.Direction,
|
|
||||||
Count = c.Count,
|
|
||||||
})
|
})
|
||||||
.ToArrayAsync();
|
.ToArrayAsync();
|
||||||
|
|
||||||
|
|
|
@ -100,10 +100,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
AccountId = tradeCommand.AccountId,
|
AccountId = tradeCommand.AccountId,
|
||||||
Figi = tradeCommand.Figi,
|
Figi = tradeCommand.Figi,
|
||||||
OrderId = res.OrderId,
|
OrderId = res.OrderId,
|
||||||
Ticker = _tradeDataProvider.GetTickerByFigi(tradeCommand.Figi),
|
Ticker = _tradeDataProvider.GetTickerByFigi(tradeCommand.Figi),
|
||||||
Count = res.LotsRequested,
|
Count = res.LotsRequested,
|
||||||
Direction = (DealDirection)(int)dir,
|
Direction = (DealDirection)(int)dir,
|
||||||
ExpirationTime = DateTime.UtcNow.AddMinutes(10),
|
ExpirationTime = DateTime.UtcNow.AddMinutes(2),
|
||||||
OpenDate = DateTime.UtcNow,
|
OpenDate = DateTime.UtcNow,
|
||||||
Price = tradeCommand.RecomendPrice.Value,
|
Price = tradeCommand.RecomendPrice.Value,
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace KLHZ.Trader.Service.Controllers
|
||||||
//var figi1 = "BBG004730N88";
|
//var figi1 = "BBG004730N88";
|
||||||
var figi2 = "BBG004730N88";
|
var figi2 = "BBG004730N88";
|
||||||
//var figi2 = "FUTIMOEXF000";
|
//var figi2 = "FUTIMOEXF000";
|
||||||
var time1 = startDate ?? DateTime.UtcNow.AddDays(-17);
|
var time1 = startDate?? DateTime.UtcNow.AddDays(-17);
|
||||||
//var time1 = new DateTime(2025, 9, 4, 14, 0, 0, DateTimeKind.Utc);
|
//var time1 = new DateTime(2025, 9, 4, 14, 0, 0, DateTimeKind.Utc);
|
||||||
//var time2 = DateTime.UtcNow.AddMinutes(18);
|
//var time2 = DateTime.UtcNow.AddMinutes(18);
|
||||||
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
|
Loading…
Reference in New Issue