klhztrader/KLHZ.Trader.Core/Exchange/Services/TradingCommandsExecutor.cs

106 lines
4.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
using KLHZ.Trader.Core.Contracts.Messaging.Interfaces;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Threading.Channels;
using Tinkoff.InvestApi;
using Tinkoff.InvestApi.V1;
namespace KLHZ.Trader.Core.Exchange.Services
{
public class TradingCommandsExecutor : IHostedService
{
private readonly TraderDataProvider _tradeDataProvider;
private readonly InvestApiClient _investApiClient;
private readonly IDataBus _dataBus;
private readonly ILogger<TradingCommandsExecutor> _logger;
private readonly Channel<ITradeCommand> _channel = Channel.CreateUnbounded<ITradeCommand>();
public TradingCommandsExecutor(InvestApiClient investApiClient, IDataBus dataBus, ILogger<TradingCommandsExecutor> logger, TraderDataProvider tradeDataProvider)
{
_investApiClient = investApiClient;
_dataBus = dataBus;
_dataBus.AddChannel(nameof(TradingCommandsExecutor), _channel);
_logger = logger;
_tradeDataProvider = tradeDataProvider;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_ = ProcessCommands();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
internal async Task ExecuteCommand(ITradeCommand tradeCommand)
{
try
{
var dir = OrderDirection.Unspecified;
var orderType = OrderType.Unspecified;
if (tradeCommand.CommandType == Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketBuy)
{
dir = OrderDirection.Buy;
orderType = OrderType.Market;
}
else if (tradeCommand.CommandType == Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketSell)
{
dir = OrderDirection.Sell;
orderType = OrderType.Market;
}
else if (tradeCommand.CommandType == Contracts.Messaging.Dtos.Enums.TradeCommandType.LimitBuy && tradeCommand.RecomendPrice.HasValue)
{
dir = OrderDirection.Buy;
orderType = OrderType.Limit;
}
var req = new PostOrderRequest()
{
AccountId = tradeCommand.AccountId,
InstrumentId = tradeCommand.Figi,
Direction = dir,
Price = tradeCommand.RecomendPrice ?? 0,
OrderType = orderType,
Quantity = tradeCommand.Count,
ConfirmMarginTrade = tradeCommand.EnableMargin,
};
_logger.LogWarning("Получена команда c id {commandId} на операцию с активом {figi}! Тип заявки сделки: {dir}; Количество активов: {count}; Разрешена ли маржиналка: {margin}",
tradeCommand.CommandId, req.InstrumentId, req.OrderType, req.Quantity, req.ConfirmMarginTrade);
var res = await _investApiClient.Orders.PostOrderAsync(req);
_logger.LogWarning("Исполнена команда c id {commandId} на операцию с активом {figi}! Направление: {dir}; Число лотов: {lots}; цена: {price}", tradeCommand.CommandId, res.Figi,
res.Direction, res.LotsExecuted, (decimal)res.ExecutedOrderPrice);
//var result = new DealResult
//{
// Count = sign * res.LotsExecuted,
// Price = res.ExecutedOrderPrice,
// Success = true,
// Direction = dealDirection,
// AccountId = tradeCommand.AccountId,
// Figi = tradeCommand.Figi,
//};
//await _tradeDataProvider.LogDeal(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при покупке актива на счёт {acc}. figi: {figi}", tradeCommand.AccountId, tradeCommand.Figi);
}
}
private async Task ProcessCommands()
{
while (await _channel.Reader.WaitToReadAsync())
{
var command = await _channel.Reader.ReadAsync();
await ExecuteCommand(command);
}
}
}
}