обновление торговой стратегии и механики сброса покупки активов
test / deploy_trader_prod (push) Successful in 12m44s
Details
test / deploy_trader_prod (push) Successful in 12m44s
Details
parent
816ad0f677
commit
ce58c7a22c
|
@ -3,11 +3,8 @@
|
|||
public enum TradeCommandType
|
||||
{
|
||||
Unknown = 0,
|
||||
|
||||
MarketBuy = 1,
|
||||
MarketSell = 101,
|
||||
LimitBuy = 200,
|
||||
LimitSell = 300,
|
||||
CancelOrder = 400,
|
||||
OpenLong = 1,
|
||||
OpenShort = 101,
|
||||
ClosePosition = 200,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@ namespace KLHZ.Trader.Core.Contracts.Messaging.Interfaces
|
|||
public bool AddChannel(string key, Channel<IOrderbook> channel);
|
||||
public bool AddChannel(string key, Channel<INewPrice> channel);
|
||||
public bool AddChannel(string key, Channel<IMessage> channel);
|
||||
public bool AddChannel(string key, Channel<ITradeCommand> channel);
|
||||
public Task Broadcast(INewPrice newPriceMessage);
|
||||
public Task Broadcast(IOrderbook orderbook);
|
||||
public Task Broadcast(IMessage message);
|
||||
public Task Broadcast(ITradeCommand message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace KLHZ.Trader.Core.Common.Messaging.Services
|
|||
{
|
||||
private readonly ConcurrentDictionary<string, Channel<IOrderbook>> _orderbooksChannels = new();
|
||||
private readonly ConcurrentDictionary<string, Channel<IMessage>> _messagesChannels = new();
|
||||
private readonly ConcurrentDictionary<string, Channel<ITradeCommand>> _commandsChannel = new();
|
||||
private readonly ConcurrentDictionary<string, Channel<INewPrice>> _priceChannels = new();
|
||||
|
||||
public bool AddChannel(string key, Channel<IMessage> channel)
|
||||
|
@ -16,6 +17,11 @@ namespace KLHZ.Trader.Core.Common.Messaging.Services
|
|||
return _messagesChannels.TryAdd(key, channel);
|
||||
}
|
||||
|
||||
public bool AddChannel(string key, Channel<ITradeCommand> channel)
|
||||
{
|
||||
return _commandsChannel.TryAdd(key, channel);
|
||||
}
|
||||
|
||||
public bool AddChannel(string key, Channel<INewPrice> channel)
|
||||
{
|
||||
return _priceChannels.TryAdd(key, channel);
|
||||
|
@ -34,6 +40,13 @@ namespace KLHZ.Trader.Core.Common.Messaging.Services
|
|||
}
|
||||
}
|
||||
|
||||
public async Task Broadcast(ITradeCommand command)
|
||||
{
|
||||
foreach (var channel in _commandsChannel.Values)
|
||||
{
|
||||
await channel.Writer.WriteAsync(command);
|
||||
}
|
||||
}
|
||||
public async Task Broadcast(IOrderbook orderbook)
|
||||
{
|
||||
foreach (var channel in _orderbooksChannels.Values)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using KLHZ.Trader.Core.Common;
|
||||
using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums;
|
||||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos;
|
||||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Enums;
|
||||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||
using KLHZ.Trader.Core.Contracts.Messaging.Interfaces;
|
||||
using KLHZ.Trader.Core.DataLayer.Entities.Declisions;
|
||||
|
@ -20,6 +21,7 @@ using System.Collections.Concurrent;
|
|||
using System.Collections.Immutable;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Channels;
|
||||
using Telegram.Bot.Types;
|
||||
using Tinkoff.InvestApi;
|
||||
using Asset = KLHZ.Trader.Core.Exchange.Models.AssetsAccounting.Asset;
|
||||
using AssetType = KLHZ.Trader.Core.Exchange.Models.AssetsAccounting.AssetType;
|
||||
|
@ -43,6 +45,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
private readonly ConcurrentDictionary<string, DateTime> ShortClosingStops = new();
|
||||
private readonly ConcurrentDictionary<string, InstrumentSettings> Leverages = new();
|
||||
|
||||
|
||||
|
||||
private readonly decimal _futureComission;
|
||||
private readonly decimal _shareComission;
|
||||
private readonly decimal _accountCashPart;
|
||||
|
@ -50,8 +54,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
private readonly string[] _tradingInstrumentsFigis = [];
|
||||
|
||||
private readonly Channel<INewPrice> _pricesChannel = Channel.CreateUnbounded<INewPrice>();
|
||||
private readonly Channel<IOrderbook> _ordersbookChannel = Channel.CreateUnbounded<IOrderbook>();
|
||||
|
||||
private readonly Channel<ITradeCommand> _commands = Channel.CreateUnbounded<ITradeCommand>();
|
||||
public Trader(
|
||||
ILogger<Trader> logger,
|
||||
IOptions<ExchangeConfig> options,
|
||||
|
@ -83,8 +86,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_dataBus.AddChannel(nameof(Trader), _pricesChannel);
|
||||
_dataBus.AddChannel(nameof(Trader), _ordersbookChannel);
|
||||
//_dataBus.AddChannel(nameof(Trader), _ordersbookChannel);
|
||||
_dataBus.AddChannel(nameof(Trader), _commands);
|
||||
_ = ProcessPrices();
|
||||
_ = ProcessCommands();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
@ -133,6 +138,43 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
return position;
|
||||
}
|
||||
|
||||
private async Task ProcessCommands()
|
||||
{
|
||||
while (await _commands.Reader.WaitToReadAsync())
|
||||
{
|
||||
var command = await _commands.Reader.ReadAsync();
|
||||
try
|
||||
{
|
||||
if (command.CommandType == Contracts.Messaging.Dtos.Enums.TradeCommandType.OpenLong
|
||||
|| command.CommandType == Contracts.Messaging.Dtos.Enums.TradeCommandType.OpenShort)
|
||||
{
|
||||
var fakeMessage = new NewPriceMessage() { Figi = command.Figi, Ticker = "", Count = command.Count, Direction = 1, IsHistoricalData = false, Time = DateTime.UtcNow, Value = command.RecomendPrice ?? 0m };
|
||||
var positionType = command.CommandType == TradeCommandType.OpenLong ? PositionType.Long : PositionType.Short;
|
||||
var stops = GetStops(fakeMessage, positionType);
|
||||
var accounts = _portfolioWrapper.Accounts
|
||||
.Where(a => !a.Value.Assets.ContainsKey(command.Figi))
|
||||
.Take(1)
|
||||
.Select(a => a.Value)
|
||||
.ToArray();
|
||||
await OpenPositions(accounts, fakeMessage, positionType, stops.stopLoss, stops.takeProfit, System.Math.Abs(command.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
var fakeMessage = new NewPriceMessage() { Figi = command.Figi, Ticker = "", Count = command.Count, Direction = 1, IsHistoricalData = false, Time = DateTime.UtcNow, Value = command.RecomendPrice ?? 0m };
|
||||
var assetsForClose = _portfolioWrapper.Accounts
|
||||
.SelectMany(a => a.Value.Assets.Values)
|
||||
.Where(a => a.Figi == fakeMessage.Figi)
|
||||
.ToArray();
|
||||
await ClosePositions(assetsForClose, fakeMessage, false);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessPrices()
|
||||
{
|
||||
var pricesCache1 = new Dictionary<string, List<INewPrice>>();
|
||||
|
@ -141,7 +183,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
while (await _pricesChannel.Reader.WaitToReadAsync())
|
||||
{
|
||||
var message = await _pricesChannel.Reader.ReadAsync();
|
||||
var changeMods = GetInitDict(1);
|
||||
var changeMods = GetInitDict(0);
|
||||
try
|
||||
{
|
||||
if (message.IsHistoricalData)
|
||||
|
@ -241,7 +283,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
}
|
||||
#endregion
|
||||
if (_tradingInstrumentsFigis.Contains(message.Figi) && message.Figi == "FUTIMOEXF000")
|
||||
if (_tradingInstrumentsFigis.Contains(message.Figi) && message.Figi == "FUTIMOEXF000" && message.Direction==1)
|
||||
{
|
||||
var currentTime = message.IsHistoricalData ? message.Time : DateTime.UtcNow;
|
||||
try
|
||||
|
@ -355,7 +397,7 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
res[TradingEvent.UptrendEnd] = Constants.PowerLowingCoefficient;
|
||||
if ((resultMoveAvFull.events & TradingEvent.UptrendStart) == TradingEvent.UptrendStart)
|
||||
{
|
||||
res[TradingEvent.UptrendStart] = 2*initValue;
|
||||
res[TradingEvent.UptrendStart] = initValue;
|
||||
res[TradingEvent.DowntrendEnd] = initValue;
|
||||
}
|
||||
if ((resultMoveAvFull.events & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
|
||||
|
@ -397,7 +439,12 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
var loggedDeclisions = 0;
|
||||
var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi);
|
||||
var assetsForClose = new List<Asset>();
|
||||
|
||||
var price = message.Value;
|
||||
if (price == 0)
|
||||
{
|
||||
price = await _tradeDataProvider.GetLastPrice(message.Figi);
|
||||
}
|
||||
var messages = new List<string>();
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (withProfitOnly)
|
||||
|
@ -406,16 +453,13 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
|
||||
if (assetType == AssetType.Futures)
|
||||
{
|
||||
profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value,
|
||||
profit = TradingCalculator.CaclProfit(asset.BoughtPrice, price,
|
||||
GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0);
|
||||
}
|
||||
if (profit > 0)
|
||||
{
|
||||
assetsForClose.Add(asset);
|
||||
await _dataBus.Broadcast(new MessageForAdmin()
|
||||
{
|
||||
Text = $"Закрываю позицию {asset.Figi} ({(asset.Count > 0 ? "лонг" : "шорт")}) на счёте {_portfolioWrapper.Accounts[asset.AccountId].AccountName}. Количество {(long)asset.Count}, цена ~{message.Value}, профит {profit}"
|
||||
});
|
||||
messages.Add($"Закрываю позицию {asset.Figi} ({(asset.Count > 0 ? "лонг" : "шорт")}) на счёте {_portfolioWrapper.Accounts[asset.AccountId].AccountName}. Количество {(long)asset.Count}, цена ~{price}, профит {profit}");
|
||||
if (loggedDeclisions == 0)
|
||||
{
|
||||
loggedDeclisions++;
|
||||
|
@ -425,12 +469,17 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
}
|
||||
else
|
||||
{
|
||||
messages.Add($"Закрываю позицию {asset.Figi} ({(asset.Count > 0 ? "лонг" : "шорт")}) на счёте {_portfolioWrapper.Accounts[asset.AccountId].AccountName}. Количество {(long)asset.Count}, цена ~{price}");
|
||||
assetsForClose.Add(asset);
|
||||
}
|
||||
}
|
||||
|
||||
var tasks = assetsForClose.Select(asset => _portfolioWrapper.Accounts[asset.AccountId].ClosePosition(message.Figi));
|
||||
await Task.WhenAll(tasks);
|
||||
foreach (var mess in messages)
|
||||
{
|
||||
await _dataBus.Broadcast(new MessageForAdmin() { Text = mess });
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OpenPositions(IManagedAccount[] accounts, INewPrice message, PositionType positionType, decimal stopLossShift, decimal takeProfitShift, long count = 1)
|
||||
|
@ -469,7 +518,7 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
return;
|
||||
}
|
||||
//var resTask1 = GetWindowAverageStartData(data, 30, 180, message, windowMaxSize, -2m, 2m,3);
|
||||
var resTask1 = GetWindowAverageStartData(data, 30, 180, message, windowMaxSize, 0m, 0.5m, Constants.PowerUppingCoefficient);
|
||||
var resTask1 = GetWindowAverageStartData(data, 30, 180, message, windowMaxSize, 0m, 0.5m, 2*Constants.PowerUppingCoefficient);
|
||||
//var resTask3 = GetWindowAverageStartData(data, 30, 180, message, windowMaxSize, 0, 0,0.7m);
|
||||
var getFFTModsTask = GetFFTMods(message);
|
||||
//var getAreasModsTask = GetAreasMods(data, message);
|
||||
|
@ -487,11 +536,11 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
|
||||
//result = MergeResults(result, resTask2.Result.ToImmutableDictionary());
|
||||
//result = MergeResults(result, resTask3.Result.ToImmutableDictionary());
|
||||
//result = MergeResults(result, changeModeData);
|
||||
result = MergeResults(result, getFFTModsTask.Result);
|
||||
result = MergeResultsMax(result, changeModeData);
|
||||
result = MergeResultsMult(result, getFFTModsTask.Result);
|
||||
//result = MergeResults(result, getAreasModsTask.Result);
|
||||
result = MergeResults(result, getSellsDiffsModsTask.Result);
|
||||
result = MergeResults(result, getTradingModeModsTask.Result);
|
||||
result = MergeResultsMult(result, getSellsDiffsModsTask.Result);
|
||||
result = MergeResultsMult(result, getTradingModeModsTask.Result);
|
||||
|
||||
if (result[TradingEvent.UptrendStart] > Constants.UppingCoefficient
|
||||
&& !LongOpeningStops.ContainsKey(message.Figi)
|
||||
|
@ -684,11 +733,11 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
{
|
||||
res = TradingMode.SlowDropping;
|
||||
}
|
||||
if (largeDataRes > 5 && smallDataRes > 0)
|
||||
if ((largeDataRes > 5 && smallDataRes > 0)||smallDataRes>7)
|
||||
{
|
||||
res = TradingMode.Growing;
|
||||
}
|
||||
if (largeDataRes < -5 && smallDataRes < 0)
|
||||
if ((largeDataRes < -5 && smallDataRes < 0)|| smallDataRes<-7)
|
||||
{
|
||||
res = TradingMode.Dropping;
|
||||
}
|
||||
|
@ -706,12 +755,11 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
private (decimal stopLoss, decimal takeProfit) GetStops(INewPrice message, PositionType type)
|
||||
{
|
||||
var mode = TradingModes[message.Figi];
|
||||
decimal stopLossShift = 4;
|
||||
decimal takeProfitShift = 5;
|
||||
decimal stopLossShift = 15;
|
||||
decimal takeProfitShift = 6;
|
||||
if (mode == TradingMode.Growing && type == PositionType.Long)
|
||||
{
|
||||
stopLossShift = 6;
|
||||
takeProfitShift = 9;
|
||||
takeProfitShift = 15;
|
||||
}
|
||||
if (mode == TradingMode.Growing && type == PositionType.Short)
|
||||
{
|
||||
|
@ -720,28 +768,24 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
}
|
||||
if (mode == TradingMode.Stable && type == PositionType.Long)
|
||||
{
|
||||
stopLossShift = 4;
|
||||
takeProfitShift = 2.5m;
|
||||
}
|
||||
if (mode == TradingMode.Stable && type == PositionType.Short)
|
||||
{
|
||||
stopLossShift = 4;
|
||||
takeProfitShift = 2.5m;
|
||||
stopLossShift = 5;
|
||||
}
|
||||
if (mode == TradingMode.SlowDropping && type == PositionType.Short)
|
||||
{
|
||||
stopLossShift = 6;
|
||||
takeProfitShift = 2.5m;
|
||||
takeProfitShift = 4m;
|
||||
}
|
||||
if (mode == TradingMode.SlowDropping && type == PositionType.Long)
|
||||
{
|
||||
stopLossShift = 4;
|
||||
takeProfitShift = 1.5m;
|
||||
}
|
||||
if (mode == TradingMode.Dropping && type == PositionType.Short)
|
||||
{
|
||||
stopLossShift = 6;
|
||||
takeProfitShift = 8;
|
||||
takeProfitShift = 15;
|
||||
}
|
||||
if (mode == TradingMode.Dropping && type == PositionType.Long)
|
||||
{
|
||||
|
@ -855,29 +899,29 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
var mode = TradingModes[message.Figi];
|
||||
if (mode == TradingMode.None)
|
||||
{
|
||||
res[TradingEvent.UptrendEnd] = Constants.UppingCoefficient;
|
||||
res[TradingEvent.UptrendStart] = 1;
|
||||
res[TradingEvent.DowntrendStart] = Constants.LowingCoefficient;
|
||||
res[TradingEvent.DowntrendEnd] = Constants.UppingCoefficient;
|
||||
//res[TradingEvent.UptrendEnd] = Constants.UppingCoefficient;
|
||||
//res[TradingEvent.UptrendStart] = 1;
|
||||
//res[TradingEvent.DowntrendStart] = Constants.LowingCoefficient;
|
||||
//res[TradingEvent.DowntrendEnd] = Constants.UppingCoefficient;
|
||||
}
|
||||
if (mode == TradingMode.Growing)
|
||||
{
|
||||
res[TradingEvent.UptrendEnd] = Constants.PowerLowingCoefficient;
|
||||
res[TradingEvent.UptrendStart] = 10;
|
||||
res[TradingEvent.DowntrendStart] = Constants.BlockingCoefficient;
|
||||
res[TradingEvent.DowntrendEnd] = Constants.BlockingCoefficient;
|
||||
res[TradingEvent.DowntrendEnd] = Constants.PowerUppingCoefficient;
|
||||
}
|
||||
if (mode == TradingMode.Stable)
|
||||
{
|
||||
res[TradingEvent.UptrendEnd] = 1;
|
||||
//res[TradingEvent.UptrendStart] = Constants.UppingCoefficient;
|
||||
//res[TradingEvent.DowntrendEnd] = Constants.UppingCoefficient;
|
||||
res[TradingEvent.DowntrendStart] = Constants.BlockingCoefficient;
|
||||
// res[TradingEvent.DowntrendStart] = Constants.BlockingCoefficient;
|
||||
}
|
||||
if (mode == TradingMode.SlowDropping)
|
||||
{
|
||||
res[TradingEvent.UptrendEnd] = Constants.PowerUppingCoefficient;
|
||||
res[TradingEvent.UptrendStart] = Constants.PowerLowingCoefficient;
|
||||
//res[TradingEvent.UptrendEnd] = Constants.PowerUppingCoefficient;
|
||||
//res[TradingEvent.UptrendStart] = Constants.PowerLowingCoefficient;
|
||||
//res[TradingEvent.DowntrendStart] = Constants.UppingCoefficient;
|
||||
//res[TradingEvent.DowntrendEnd] = Constants.UppingCoefficient;
|
||||
}
|
||||
|
@ -918,7 +962,7 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
return values.ToDictionary(v => v, v => initValue);
|
||||
}
|
||||
|
||||
private static Dictionary<TradingEvent, decimal> MergeResults(Dictionary<TradingEvent, decimal> res, ImmutableDictionary<TradingEvent, decimal> data)
|
||||
private static Dictionary<TradingEvent, decimal> MergeResultsMult(Dictionary<TradingEvent, decimal> res, ImmutableDictionary<TradingEvent, decimal> data)
|
||||
{
|
||||
foreach (var k in res.Keys)
|
||||
{
|
||||
|
@ -928,5 +972,16 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static Dictionary<TradingEvent, decimal> MergeResultsMax(Dictionary<TradingEvent, decimal> res, ImmutableDictionary<TradingEvent, decimal> data)
|
||||
{
|
||||
foreach (var k in res.Keys)
|
||||
{
|
||||
var valRes = res[k];
|
||||
var valData = data[k];
|
||||
res[k] = System.Math.Max(valRes, valData);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
|
||||
private readonly bool _isDataRecievingAllowed = false;
|
||||
private readonly Channel<object> _forSave = Channel.CreateUnbounded<object>();
|
||||
|
||||
private readonly SemaphoreSlim _initSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
public TraderDataProvider(InvestApiClient investApiClient, IOptions<ExchangeConfig> options, IDbContextFactory<TraderDbContext> dbContextFactory, ILogger<TraderDataProvider> logger)
|
||||
|
@ -61,6 +62,16 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
public async ValueTask<decimal> GetLastPrice(string figi)
|
||||
{
|
||||
var res = 0m;
|
||||
if (_historyCash.TryGetValue(figi, out var unit))
|
||||
{
|
||||
res = (await unit.GetLastValues()).price;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public async ValueTask<(DateTime[] timestamps, decimal[] prices, bool isFullIntervalExists)> GetData(string figi, TimeSpan timeSpan)
|
||||
{
|
||||
if (_historyCash.TryGetValue(figi, out var unit))
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using KLHZ.Trader.Core.Common;
|
||||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos;
|
||||
using KLHZ.Trader.Core.Contracts.Messaging.Interfaces;
|
||||
using KLHZ.Trader.Core.Exchange.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -78,30 +79,41 @@ namespace KLHZ.Trader.Core.TG.Services
|
|||
case "скинуть IMOEXF":
|
||||
case "сбросить IMOEXF":
|
||||
{
|
||||
|
||||
var assets = _portfolioWrapper.Accounts
|
||||
.SelectMany(a => a.Value.Assets)
|
||||
.Select(a => a.Value)
|
||||
.Where(a => a.Figi == "FUTIMOEXF000");
|
||||
foreach (var asset in assets)
|
||||
var command = new TradeCommand()
|
||||
{
|
||||
await _portfolioWrapper.Accounts[asset.AccountId].ClosePosition("FUTIMOEXF000");
|
||||
}
|
||||
|
||||
AccountId = "",
|
||||
Figi = "FUTIMOEXF000",
|
||||
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.ClosePosition,
|
||||
EnableMargin = true,
|
||||
Count = 1
|
||||
};
|
||||
await _eventBus.Broadcast(command);
|
||||
break;
|
||||
}
|
||||
case "лонг IMOEXF":
|
||||
{
|
||||
var acc = _portfolioWrapper.Accounts.Values.FirstOrDefault(a => !a.Assets.ContainsKey("FUTIMOEXF000"));
|
||||
if (acc != null)
|
||||
await acc.OpenPosition("FUTIMOEXF000", Exchange.Models.AssetsAccounting.PositionType.Long, 4, 6, 1);
|
||||
var command = new TradeCommand()
|
||||
{
|
||||
AccountId = "",
|
||||
Figi = "FUTIMOEXF000",
|
||||
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.OpenLong,
|
||||
EnableMargin = true,
|
||||
Count = 1
|
||||
};
|
||||
await _eventBus.Broadcast(command);
|
||||
break;
|
||||
}
|
||||
case "шорт IMOEXF":
|
||||
{
|
||||
var acc = _portfolioWrapper.Accounts.Values.FirstOrDefault(a => !a.Assets.ContainsKey("FUTIMOEXF000"));
|
||||
if (acc != null)
|
||||
await acc.OpenPosition("FUTIMOEXF000", Exchange.Models.AssetsAccounting.PositionType.Short, 4, 6, 1);
|
||||
var command = new TradeCommand()
|
||||
{
|
||||
AccountId = "",
|
||||
Figi = "FUTIMOEXF000",
|
||||
CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.OpenShort,
|
||||
EnableMargin = true,
|
||||
Count = 1
|
||||
};
|
||||
await _eventBus.Broadcast(command);
|
||||
break;
|
||||
}
|
||||
case "stops":
|
||||
|
|
|
@ -34,8 +34,8 @@ namespace KLHZ.Trader.Service.Controllers
|
|||
//var figi1 = "BBG004730N88";
|
||||
var figi2 = "BBG004730N88";
|
||||
//var figi2 = "FUTIMOEXF000";
|
||||
var time1 = DateTime.UtcNow.AddDays(-shift ?? -7).Date;
|
||||
//var time1 = new DateTime(2025, 9, 4, 14, 0, 0, DateTimeKind.Utc);
|
||||
//var time1 = DateTime.UtcNow.AddDays(-shift ?? -7).Date;
|
||||
var time1 = new DateTime(2025, 9, 23, 17, 0, 0, DateTimeKind.Utc);
|
||||
//var time2 = DateTime.UtcNow.AddMinutes(18);
|
||||
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
||||
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
|
|
Loading…
Reference in New Issue