чистка мусора + доработка вывода результатов
test / deploy_trader_prod (push) Successful in 11m24s
Details
test / deploy_trader_prod (push) Successful in 11m24s
Details
parent
b3b7807249
commit
6770d12640
|
@ -82,7 +82,6 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return (resDt, resVs);
|
||||
}
|
||||
|
||||
|
||||
public static (DateTime[] timestamps, decimal[] values) TrimValues(DateTime[] timestamps, decimal[] values, TimeSpan leftBound, TimeSpan rightBound)
|
||||
{
|
||||
var resDt = new List<DateTime>();
|
||||
|
|
|
@ -232,7 +232,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
}
|
||||
|
||||
public static (TradingEvent events, decimal bigWindowAv, decimal smallWindowAv) CheckByWindowAverageMean2(ITradeDataItem[] data, int size, int smallWindow, int bigWindow,
|
||||
decimal? uptrendStartingDetectionMeanfullStep = null, decimal? uptrendEndingDetectionMeanfullStep = null)
|
||||
decimal? uptrendStartingDetectionMeanfullStep = null, decimal? uptrendEndingDetectionMeanfullStep = null)
|
||||
{
|
||||
var res = TradingEvent.None;
|
||||
var bigWindowAv = 0m;
|
||||
|
|
|
@ -5,7 +5,6 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
{
|
||||
public static class Statistics
|
||||
{
|
||||
|
||||
public static decimal MeanCount(this ITradeDataItem[] values)
|
||||
{
|
||||
return values.Sum(x => x.Count) / values.Length;
|
||||
|
@ -197,25 +196,5 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
}
|
||||
return Array.Empty<ConvolutionResult>();
|
||||
}
|
||||
|
||||
public static void MergeConvolutionResults(List<ConvolutionResult> results, List<ConvolutionResult> mergedResults)
|
||||
{
|
||||
if (results.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var resultsOrdered = results.OrderBy(r => r.Sum).ToList();
|
||||
var res = resultsOrdered[0];
|
||||
var b1 = res.Shift - res.Leverage;
|
||||
var b2 = res.Shift + res.Leverage;
|
||||
var forMerge = results.Where(r => r.Shift >= b1 && r.Shift <= b2).ToList();
|
||||
res.Sum = forMerge.Sum(r => r.Sum);
|
||||
foreach (var m in forMerge)
|
||||
{
|
||||
results.Remove(m);
|
||||
}
|
||||
mergedResults.Add(res);
|
||||
MergeConvolutionResults(results, mergedResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using KLHZ.Trader.Core.Contracts.Common.Enums;
|
||||
using KLHZ.Trader.Core.Exchange.Models.AssetsAccounting;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Trading;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace KLHZ.Trader.Core.Exchange.Interfaces
|
||||
|
@ -14,8 +15,8 @@ namespace KLHZ.Trader.Core.Exchange.Interfaces
|
|||
Task Init(string accountId, string? accountName = null);
|
||||
Task LoadPortfolio();
|
||||
ImmutableDictionary<string, Asset> Assets { get; }
|
||||
public Task OpenPosition(string figi, PositionType positionType, decimal stopLossShift, decimal takeProfitShift, long count = 1);
|
||||
public Task ClosePosition(string figi);
|
||||
public Task<TradeResult> OpenPosition(string figi, PositionType positionType, decimal stopLossShift, decimal takeProfitShift, long count = 1, decimal pointPrice = 1);
|
||||
public Task<TradeResult> ClosePosition(string figi);
|
||||
public Task ResetStops(string figi, decimal stopLossShift, decimal takeProfitShift);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
public required string Figi { get; init; }
|
||||
public decimal ShortLeverage { get; init; }
|
||||
public decimal LongLeverage { get; init; }
|
||||
public decimal PriceToRubConvertationCoefficient { get; init; } = 1;
|
||||
public decimal PointPriceRub { get; init; } = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
namespace KLHZ.Trader.Core.Exchange.Models.Trading
|
||||
{
|
||||
public class TradeResult
|
||||
{
|
||||
public bool Success { get; init; }
|
||||
public decimal ExecutedPrice { get; init; }
|
||||
public decimal Comission { get; init; }
|
||||
public long Count { get; init; }
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
namespace KLHZ.Trader.Core.Exchange.Models.Trading
|
||||
{
|
||||
public enum TradingMode
|
||||
{
|
||||
None = 0,
|
||||
Stable = 1,
|
||||
SlowDropping = -1,
|
||||
SlowGrowing = 2,
|
||||
Growing = 3,
|
||||
Dropping = -2,
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using KLHZ.Trader.Core.DataLayer;
|
|||
using KLHZ.Trader.Core.Exchange.Extentions;
|
||||
using KLHZ.Trader.Core.Exchange.Interfaces;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Configs;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Trading;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
@ -164,8 +165,9 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
Balance = portfolio.TotalAmountCurrencies;
|
||||
}
|
||||
|
||||
public async Task OpenPosition(string figi, PositionType positionType, decimal stopLossShift, decimal takeProfitShift, long count = 1)
|
||||
public async Task<TradeResult> OpenPosition(string figi, PositionType positionType, decimal stopLossShift, decimal takeProfitShift, long count = 1, decimal pointPrice = 1)
|
||||
{
|
||||
TradeResult? result = null;
|
||||
try
|
||||
{
|
||||
await _semaphore.WaitAsync2(_defaultLockTimeSpan);
|
||||
|
@ -186,58 +188,54 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
var res = await _investApiClient.Orders.PostOrderAsync(req);
|
||||
|
||||
_usedOrderIds.TryAdd(res.OrderId, DateTime.UtcNow);
|
||||
var executedPrice = res.ExecutedOrderPrice / 10;
|
||||
var executedPrice = res.ExecutedOrderPrice / pointPrice;
|
||||
|
||||
await Task.Delay(1000);
|
||||
|
||||
if (stopLossShift == 0)
|
||||
if (stopLossShift != 0)
|
||||
{
|
||||
stopLossShift = 0.002m * executedPrice;
|
||||
var pricesl = positionType == PositionType.Long ? executedPrice - stopLossShift : executedPrice + stopLossShift;
|
||||
var slReq = new PostStopOrderRequest()
|
||||
{
|
||||
AccountId = AccountId,
|
||||
ConfirmMarginTrade = false,
|
||||
InstrumentId = figi,
|
||||
Direction = stopOrdersDirection,
|
||||
PriceType = PriceType.Point,
|
||||
Quantity = count,
|
||||
StopOrderType = StopOrderType.StopLoss,
|
||||
StopPrice = pricesl,
|
||||
ExchangeOrderType = ExchangeOrderType.Market,
|
||||
ExpirationType = StopOrderExpirationType.GoodTillCancel,
|
||||
};
|
||||
var slOrderRes = await _investApiClient.StopOrders.PostStopOrderAsync(slReq);
|
||||
}
|
||||
if (takeProfitShift == 0)
|
||||
|
||||
if (takeProfitShift != 0)
|
||||
{
|
||||
takeProfitShift = 0.01m * executedPrice;
|
||||
var pricetp = positionType == PositionType.Long ? executedPrice + takeProfitShift : executedPrice - takeProfitShift;
|
||||
var tpReq = new PostStopOrderRequest()
|
||||
{
|
||||
AccountId = AccountId,
|
||||
ConfirmMarginTrade = false,
|
||||
InstrumentId = figi,
|
||||
Direction = stopOrdersDirection,
|
||||
PriceType = PriceType.Point,
|
||||
Quantity = count,
|
||||
StopOrderType = StopOrderType.TakeProfit,
|
||||
StopPrice = pricetp,
|
||||
ExchangeOrderType = ExchangeOrderType.Market,
|
||||
ExpirationType = StopOrderExpirationType.GoodTillCancel,
|
||||
};
|
||||
var tpOrderRes = await _investApiClient.StopOrders.PostStopOrderAsync(tpReq);
|
||||
}
|
||||
takeProfitShift = takeProfitShift * 2;
|
||||
takeProfitShift = System.Math.Round(takeProfitShift);
|
||||
takeProfitShift = takeProfitShift / 2;
|
||||
|
||||
stopLossShift = stopLossShift * 2;
|
||||
stopLossShift = System.Math.Round(stopLossShift);
|
||||
stopLossShift = stopLossShift / 2;
|
||||
|
||||
var pricesl = positionType == PositionType.Long ? executedPrice - stopLossShift : executedPrice + stopLossShift;
|
||||
var pricetp = positionType == PositionType.Long ? executedPrice + takeProfitShift : executedPrice - takeProfitShift;
|
||||
var slReq = new PostStopOrderRequest()
|
||||
{
|
||||
AccountId = AccountId,
|
||||
ConfirmMarginTrade = false,
|
||||
InstrumentId = figi,
|
||||
Direction = stopOrdersDirection,
|
||||
PriceType = PriceType.Point,
|
||||
Quantity = count,
|
||||
StopOrderType = StopOrderType.StopLoss,
|
||||
StopPrice = pricesl,
|
||||
ExchangeOrderType = ExchangeOrderType.Market,
|
||||
ExpirationType = StopOrderExpirationType.GoodTillCancel,
|
||||
};
|
||||
var slOrderRes = await _investApiClient.StopOrders.PostStopOrderAsync(slReq);
|
||||
|
||||
var tpReq = new PostStopOrderRequest()
|
||||
{
|
||||
AccountId = AccountId,
|
||||
ConfirmMarginTrade = false,
|
||||
InstrumentId = figi,
|
||||
Direction = stopOrdersDirection,
|
||||
PriceType = PriceType.Point,
|
||||
Quantity = count,
|
||||
StopOrderType = StopOrderType.TakeProfit,
|
||||
StopPrice = pricetp,
|
||||
ExchangeOrderType = ExchangeOrderType.Market,
|
||||
ExpirationType = StopOrderExpirationType.GoodTillCancel,
|
||||
};
|
||||
var tpOrderRes = await _investApiClient.StopOrders.PostStopOrderAsync(tpReq);
|
||||
await LoadPortfolioNolock();
|
||||
result = new TradeResult()
|
||||
{
|
||||
Success = true,
|
||||
Comission = res.ExecutedCommission,
|
||||
Count = res.LotsExecuted,
|
||||
ExecutedPrice = res.ExecutedOrderPrice,
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException) { }
|
||||
|
@ -247,6 +245,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
|
||||
_semaphore.Release();
|
||||
result ??= new TradeResult();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task ResetStops(string figi, decimal stopLossShift, decimal takeProfitShift)
|
||||
|
@ -317,8 +317,9 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
_semaphore.Release();
|
||||
}
|
||||
|
||||
public async Task ClosePosition(string figi)
|
||||
public async Task<TradeResult> ClosePosition(string figi)
|
||||
{
|
||||
TradeResult? result = null;
|
||||
try
|
||||
{
|
||||
await _semaphore.WaitAsync2(_defaultLockTimeSpan);
|
||||
|
@ -355,6 +356,13 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
|
||||
await LoadPortfolioNolock();
|
||||
result = new TradeResult()
|
||||
{
|
||||
Success = true,
|
||||
Comission = res.ExecutedCommission,
|
||||
Count = res.LotsExecuted,
|
||||
ExecutedPrice = res.ExecutedOrderPrice,
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException) { }
|
||||
|
@ -364,6 +372,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
|
||||
_semaphore.Release();
|
||||
result ??= new TradeResult();
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task CyclingOperations()
|
||||
|
|
|
@ -32,12 +32,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
private readonly ExchangeConfig _exchangeConfig;
|
||||
private readonly ILogger<Trader> _logger;
|
||||
|
||||
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> _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();
|
||||
|
@ -59,10 +57,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
_logger = logger;
|
||||
_dataBus = dataBus;
|
||||
_exchangeConfig = options.Value;
|
||||
foreach (var f in _exchangeConfig.TradingInstrumentsFigis)
|
||||
{
|
||||
TradingModes[f] = TradingMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
|
@ -481,32 +475,27 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
{
|
||||
Asset? assetForClose = null;
|
||||
string? mess = null;
|
||||
var profit = 0m;
|
||||
if (withProfitOnly)
|
||||
{
|
||||
var profit = 0m;
|
||||
|
||||
if (assetType == AssetType.Futures)
|
||||
if (_tradeDataProvider.Orderbooks.TryGetValue(message.Figi, out var orderbook))
|
||||
{
|
||||
if (_tradeDataProvider.Orderbooks.TryGetValue(message.Figi, out var orderbook))
|
||||
if (asset.Count < 0 && orderbook.Asks.Length > 0)
|
||||
{
|
||||
if (asset.Count < 0 && orderbook.Asks.Length > 0)
|
||||
{
|
||||
price = orderbook.Asks[0].Price;
|
||||
}
|
||||
else if (orderbook.Bids.Length > 0)
|
||||
{
|
||||
price = orderbook.Bids[0].Price;
|
||||
}
|
||||
price = orderbook.Asks[0].Price;
|
||||
}
|
||||
else if (orderbook.Bids.Length > 0)
|
||||
{
|
||||
price = orderbook.Bids[0].Price;
|
||||
}
|
||||
|
||||
profit = TradingCalculator.CaclProfit(asset.BoughtPrice, price,
|
||||
GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0);
|
||||
}
|
||||
|
||||
profit = TradingCalculator.CaclProfit(asset.BoughtPrice, price,
|
||||
GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0);
|
||||
if (profit > 0)
|
||||
{
|
||||
profit = System.Math.Round(profit, 2);
|
||||
assetForClose = asset;
|
||||
mess = $"Закрываю позицию {asset.Figi} ({(asset.Count > 0 ? "лонг" : "шорт")}) на счёте {_portfolioWrapper.Accounts[asset.AccountId].AccountName}. Количество {(long)asset.Count}, цена ~{price}, профит {profit}";
|
||||
if (loggedDeclisions == 0)
|
||||
{
|
||||
loggedDeclisions++;
|
||||
|
@ -516,13 +505,23 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
else
|
||||
{
|
||||
mess = $"Закрываю позицию {asset.Figi} ({(asset.Count > 0 ? "лонг" : "шорт")}) на счёте {_portfolioWrapper.Accounts[asset.AccountId].AccountName}. Количество {(long)asset.Count}, цена ~{price}";
|
||||
assetForClose = asset;
|
||||
}
|
||||
|
||||
if (assetForClose != null && mess != null)
|
||||
if (assetForClose != null)
|
||||
{
|
||||
await _portfolioWrapper.Accounts[asset.AccountId].ClosePosition(message.Figi);
|
||||
var settings = _exchangeConfig.InstrumentsSettings.FirstOrDefault(l => l.Figi == message.Figi);
|
||||
var closingResult = await _portfolioWrapper.Accounts[asset.AccountId].ClosePosition(message.Figi);
|
||||
if (closingResult.Success)
|
||||
{
|
||||
var profitText = profit == 0 ? string.Empty : ", профит {profit}";
|
||||
mess = $"Закрываю позицию {asset.Figi} ({(asset.Count > 0 ? "лонг" : "шорт")}) на счёте {_portfolioWrapper.Accounts[asset.AccountId].AccountName}. Количество {(long)asset.Count}, цена ~{closingResult.ExecutedPrice / (settings?.PointPriceRub ?? 1)}, комиссия {closingResult.Comission}" + profitText;
|
||||
}
|
||||
else
|
||||
{
|
||||
mess = $"Закрытие позиции прошло с ошибками.";
|
||||
}
|
||||
|
||||
await _dataBus.Broadcast(new MessageForAdmin() { Text = mess });
|
||||
}
|
||||
}
|
||||
|
@ -537,12 +536,20 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
{
|
||||
if (TraderUtils.IsOperationAllowed(acc, message.Price, count, _exchangeConfig.AccountCashPartFutures, _exchangeConfig.AccountCashPart))
|
||||
{
|
||||
await acc.OpenPosition(message.Figi, positionType, stopLossShift, takeProfitShift, count);
|
||||
var settings = _exchangeConfig.InstrumentsSettings.FirstOrDefault(l => l.Figi == message.Figi);
|
||||
takeProfitShift = takeProfitShift * 2;
|
||||
takeProfitShift = System.Math.Round(takeProfitShift);
|
||||
takeProfitShift = takeProfitShift / 2;
|
||||
|
||||
stopLossShift = stopLossShift * 2;
|
||||
stopLossShift = System.Math.Round(stopLossShift);
|
||||
stopLossShift = stopLossShift / 2;
|
||||
var openingResult = await acc.OpenPosition(message.Figi, positionType, stopLossShift, takeProfitShift, count, settings?.PointPriceRub ?? 1);
|
||||
await _dataBus.Broadcast(new MessageForAdmin()
|
||||
{
|
||||
Text = $"Открываю позицию {message.Figi} ({(positionType == PositionType.Long ? "лонг" : "шорт")}) " +
|
||||
$"на счёте {acc.AccountName}. Количество {(positionType == PositionType.Long ? "" : "-")}{count}, " +
|
||||
$"цена ~{System.Math.Round(message.Price, 2)}. Стоп лосс: {(positionType == PositionType.Long ? "-" : "+")}{stopLossShift}. " +
|
||||
$"на счёте {acc.AccountName}. Количество {(positionType == PositionType.Long ? "" : "-")}{openingResult.Count}, " +
|
||||
$"цена ~{System.Math.Round(openingResult.ExecutedPrice / (settings?.PointPriceRub ?? 1), 2)}. Комиссия:{System.Math.Round(openingResult.Comission, 2)}. Стоп лосс: {(positionType == PositionType.Long ? "-" : "+")}{stopLossShift}. " +
|
||||
$"Тейк профит: {(positionType == PositionType.Long ? "+" : "-")}{takeProfitShift}"
|
||||
});
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"Figi": "FUTIMOEXF000",
|
||||
"LongLeverage": 10.3,
|
||||
"ShortLeverage": 7.9,
|
||||
"PriceToRubConvertationCoefficient" : 1
|
||||
"PointPriceRub": 10
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue