diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs index 4670e08..1938e5f 100644 --- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs +++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs @@ -1,6 +1,7 @@ using KLHZ.Trader.Core.Common; using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums; using KLHZ.Trader.Core.Contracts.Declisions.Interfaces; +using KLHZ.Trader.Core.Contracts.Messaging.Dtos; using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces; using KLHZ.Trader.Core.Contracts.Messaging.Interfaces; using KLHZ.Trader.Core.DataLayer; @@ -125,7 +126,31 @@ namespace KLHZ.Trader.Core.Exchange.Services DeferredLongOpens.TryRemove(message.Figi, out _); if (message.Value - longOpen.Price < 1) { - LogDeclision(declisionsForSave, DeclisionTradeAction.OpenLong, message); + if (!message.IsHistoricalData) + { + var accounts = _tradeDataProvider.Accounts + .Where(a => !a.Value.Assets.ContainsKey(message.Figi)) + .ToArray(); + foreach (var acc in accounts) + { + if (IsBuyAllowed(acc.Value, message.Value, 1)) + { + await _dataBus.Broadcast(new TradeCommand() + { + AccountId = acc.Value.AccountId, + Figi = message.Figi, + CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketBuy, + Count = 1, + RecomendPrice = null, + }); + LogDeclision(declisionsForSave, DeclisionTradeAction.OpenLong, message); + } + } + } + else + { + LogDeclision(declisionsForSave, DeclisionTradeAction.OpenLong, message); + } } } } @@ -139,7 +164,44 @@ namespace KLHZ.Trader.Core.Exchange.Services DeferredLongCloses.TryRemove(message.Figi, out _); if (longClose.Price - message.Value < 1) { - LogDeclision(declisionsForSave, DeclisionTradeAction.CloseLong, message); + if (!message.IsHistoricalData) + { + 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) + { + var profit = 0m; + var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi); + 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) + { + await _dataBus.Broadcast(new TradeCommand() + { + AccountId = asset.AccountId, + Figi = message.Figi, + CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketSell, + Count = (long)asset.Count, + RecomendPrice = null, + }); + LogDeclision(declisionsForSave, DeclisionTradeAction.CloseLong, message); + } + } + } + else + { + LogDeclision(declisionsForSave, DeclisionTradeAction.CloseLong, message); + } } } } @@ -333,46 +395,25 @@ namespace KLHZ.Trader.Core.Exchange.Services } } - private decimal CalcProfit(string accountId, string figi, decimal closePrice) + private decimal GetLeverage(string figi, bool isShort) { - if (_tradeDataProvider.Accounts.TryGetValue(accountId, out var account)) + var res = 1m; + if (Leverages.TryGetValue(figi, out var leverage)) { - if (account.Assets.TryGetValue(figi, out var asset)) - { - var leverageValue = 1m; - var isShort = asset.Position == PositionType.Short; - if (Leverages.TryGetValue(figi, out var leverage)) - { - if (asset.Type == AssetType.Futures && !isShort) - { - leverageValue = leverage.LongLeverage; - } - else if (isShort) - { - leverageValue = leverage.ShortLeverage; - } - } - return TradingCalculator.CaclProfit(asset.BoughtPrice, closePrice, GetComission(asset.Type), leverageValue, isShort); - } + res = isShort ? leverage.ShortLeverage : leverage.LongLeverage; } - return 0; + return res; } - private decimal GetCount(string accountId, decimal boutPrice) - { - var balance = _tradeDataProvider.Accounts[accountId].Balance; - return System.Math.Floor(balance * _defaultBuyPartOfAccount / boutPrice); - } - - private bool IsBuyAllowed(string accountId, decimal boutPrice, decimal count, bool needBigCash) + private bool IsBuyAllowed(ManagedAccount account, decimal boutPrice, decimal count) { if (!_botModeSwitcher.CanPurchase()) return false; - var balance = _tradeDataProvider.Accounts[accountId].Balance; - var total = _tradeDataProvider.Accounts[accountId].Total; + var balance = account.Balance; + var total = account.Total; - var futures = _tradeDataProvider.Accounts[accountId].Assets.Values.FirstOrDefault(v => v.Type == AssetType.Futures); - if (futures != null || needBigCash) + var futures = account.Assets.Values.FirstOrDefault(v => v.Type == AssetType.Futures); + if (futures != null) { if ((balance - boutPrice * count) / total < _accountCashPartFutures) return false; }