обновление стратегии
test / deploy_trader_prod (push) Successful in 2m14s
Details
test / deploy_trader_prod (push) Successful in 2m14s
Details
parent
f7cecbe44a
commit
ecd9a70e2e
|
@ -1,4 +1,5 @@
|
|||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace KLHZ.Trader.Core.Contracts.Messaging.Dtos
|
||||
{
|
||||
|
@ -13,5 +14,27 @@ namespace KLHZ.Trader.Core.Contracts.Messaging.Dtos
|
|||
public int Direction { get; set; }
|
||||
public decimal Value { get; init; }
|
||||
public decimal Value2 { get; init; }
|
||||
[NotMapped]
|
||||
public AttachedInfo? AttachedInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
return _attachedInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAttachedInfo(AttachedInfo? attachedInfo)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
_attachedInfo = attachedInfo;
|
||||
}
|
||||
}
|
||||
|
||||
private AttachedInfo? _attachedInfo;
|
||||
private readonly object _locker = new();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums;
|
||||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||
using MathNet.Numerics;
|
||||
|
||||
namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||||
|
@ -116,5 +117,34 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryCalcTrendDiff(ITradeDataItem[] data, out decimal diff)
|
||||
{
|
||||
diff = 0;
|
||||
if (data.Length <= 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var startTime = data[0].Time;
|
||||
var x = new double[data.Length];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
x[i] = (data[i].Time - startTime).TotalSeconds;
|
||||
}
|
||||
if (x.Min() == x.Max())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var line = Fit.Line(x.ToArray(), data.Select(d => (double)d.Price).ToArray());
|
||||
|
||||
var p1 = line.A + line.B * 0;
|
||||
var p2 = line.A + line.B * (data[data.Length - 1].Time - data[0].Time).TotalSeconds;
|
||||
|
||||
diff = (decimal)(p2 - p1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using KLHZ.Trader.Core.Exchange.Models.Trading;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Trading.Enums;
|
||||
using KLHZ.Trader.Core.Exchange.Utils;
|
||||
|
||||
namespace KLHZ.Trader.Core.Tests
|
||||
|
|
|
@ -7,8 +7,6 @@ namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
|||
[Table("price_changes")]
|
||||
public class PriceChange : ITradeDataItem
|
||||
{
|
||||
private readonly object _locker = new();
|
||||
|
||||
[Column("id")]
|
||||
public long Id { get; set; }
|
||||
|
||||
|
@ -59,5 +57,6 @@ namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
|||
}
|
||||
|
||||
private AttachedInfo? _attachedInfo;
|
||||
private readonly object _locker = new();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,24 +2,14 @@
|
|||
{
|
||||
internal static class Constants
|
||||
{
|
||||
internal const string _1minCacheKey = "1min";
|
||||
internal const string _15minSellCacheKey = "5min_sell";
|
||||
internal const string _5minSellCacheKey = "5min_sell";
|
||||
internal const string _5minBuyCacheKey = "5min_buy";
|
||||
internal const string _15minBuyCacheKey = "5min_buy";
|
||||
internal const string _1minSellCacheKey = "1min_sell";
|
||||
internal const string _1minBuyCacheKey = "1min_buy";
|
||||
|
||||
internal const string BigWindowCrossingAverageProcessor = "Trader_big";
|
||||
internal const string SmallWindowCrossingAverageProcessor = "Trader_small";
|
||||
internal const string AreasRelationProcessor = "balancescalc30min";
|
||||
internal readonly static TimeSpan AreasRelationWindow = TimeSpan.FromMinutes(15);
|
||||
|
||||
internal const decimal ForceExecuteCoefficient = 500000m;
|
||||
internal const decimal PowerUppingCoefficient = 1.69m;
|
||||
internal const decimal UppingCoefficient = 1.3m;
|
||||
internal const decimal LowingCoefficient = .76m;
|
||||
internal const decimal PowerLowingCoefficient = .59m;
|
||||
internal const decimal BlockingCoefficient = 0.01m;
|
||||
|
||||
internal const string PriceIsInSupportLevel = "PriceIsInSupportLevel";
|
||||
internal const string PriceIsNotInSupportLevel = "PriceIsNotInSupportLevel";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace KLHZ.Trader.Core.Exchange.Models.Trading
|
||||
namespace KLHZ.Trader.Core.Exchange.Models.Trading.Enums
|
||||
{
|
||||
internal enum ExchangeState
|
||||
{
|
|
@ -0,0 +1,14 @@
|
|||
namespace KLHZ.Trader.Core.Exchange.Models.Trading.Enums
|
||||
{
|
||||
[Flags]
|
||||
internal enum TradingMode
|
||||
{
|
||||
None = 0,
|
||||
Growing = 1,
|
||||
Falling = 2,
|
||||
InSupportLevel = 4,
|
||||
TryingGrowFromSupportLevel = 8,
|
||||
TryingFallFromSupportLevel = 16,
|
||||
Bezpont = 32,
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ using KLHZ.Trader.Core.Exchange.Interfaces;
|
|||
using KLHZ.Trader.Core.Exchange.Models.AssetsAccounting;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Configs;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Trading;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Trading.Enums;
|
||||
using KLHZ.Trader.Core.Exchange.Utils;
|
||||
using KLHZ.Trader.Core.Math.Declisions.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
@ -37,6 +38,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
private readonly ConcurrentDictionary<string, LinkedList<SupportLevel[]>> SupportLevelsHistory = new();
|
||||
|
||||
private readonly ConcurrentDictionary<string, DateTime> _supportLevelsCalculationTimes = new();
|
||||
private readonly ConcurrentDictionary<string, DateTime> _marginCloses = new();
|
||||
private readonly ConcurrentDictionary<string, DateTime> _usedSupportLevels = new();
|
||||
private readonly ConcurrentDictionary<string, DateTime> _usedSupportLevelsForClosing = new();
|
||||
private readonly ConcurrentDictionary<string, ITradeDataItem> _oldItems = new();
|
||||
|
@ -169,52 +171,173 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
{
|
||||
if (message.Figi == "FUTIMOEXF000")
|
||||
{
|
||||
await CalcSupportLevels(message, 2, 3);
|
||||
await CalcSupportLevels(message, 3, 3);
|
||||
var processSupportLevelsRes = await ProcessSupportLevels(message);
|
||||
|
||||
var mode = await CalcTradingMode(message);
|
||||
var stops = GetStops(message);
|
||||
if ((mode & TradingMode.InSupportLevel) == TradingMode.InSupportLevel)
|
||||
{
|
||||
if ((mode & TradingMode.Bezpont) == TradingMode.Bezpont)
|
||||
{
|
||||
|
||||
var declisionsSupportLevels = await ProcessSupportLevels(message);
|
||||
//var pirson = await CalcPirson(message);
|
||||
//var mavRes = await CalcTimeWindowAverageValue(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
var mavRes = await CalcTimeWindowAverageValue(message, true);
|
||||
await ExecuteDeclisions(mavRes, message, stops, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var mavRes = await CalcTimeWindowAverageValue(message);
|
||||
var pirson = await CalcPirson(message);
|
||||
var declisionPirson = ProcessPirson(pirson, message);
|
||||
var declisionsStops = ProcessStops(stops, 2m);
|
||||
var tradingModeResult = ProcessTradingMode(mode);
|
||||
|
||||
//var declisionPirson = ProcessPirson(pirson, message);
|
||||
//var declisionsStops = ProcessStops(stops, 2m);
|
||||
var res = TraderUtils.MergeResultsMult(declisionPirson, processSupportLevelsRes);
|
||||
res = TraderUtils.MergeResultsMult(res, declisionsStops);
|
||||
res = TraderUtils.MergeResultsMult(res, tradingModeResult);
|
||||
res = TraderUtils.MergeResultsMax(res, mavRes);
|
||||
|
||||
|
||||
//var res = TraderUtils.MergeResultsMult(declisionPirson, declisionsSupportLevels);
|
||||
//res = TraderUtils.MergeResultsMult(res, declisionsStops);
|
||||
//res = TraderUtils.MergeResultsMax(res, mavRes);
|
||||
|
||||
//await ExecuteDeclisions(res.ToImmutableDictionary(), message, stops, 1);
|
||||
await ExecuteDeclisions(res.ToImmutableDictionary(), message, stops, 1);
|
||||
}
|
||||
_oldItems[message.Figi] = message;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CheckTradingMode()
|
||||
private async Task<TradingMode> CalcTradingMode(ITradeDataItem message)
|
||||
{
|
||||
var res = TradingMode.None;
|
||||
|
||||
//var res1hour = await CalcTradingMode(message, TimeSpan.FromMinutes(60),8);
|
||||
//var res30min = await CalcTradingMode(message, TimeSpan.FromMinutes(30),6);
|
||||
|
||||
var res20min = await CalcTradingMode(message, TimeSpan.FromMinutes(20), 3);
|
||||
var res10min = await CalcTradingMode(message, TimeSpan.FromMinutes(10), 3);
|
||||
//res |= res1hour;
|
||||
//res|=res30min;
|
||||
res |= res20min;
|
||||
res &= res10min;
|
||||
|
||||
if ((res & TradingMode.TryingGrowFromSupportLevel) == TradingMode.TryingGrowFromSupportLevel)
|
||||
{
|
||||
await _tradeDataProvider.LogPrice(message, "TryingGrowFromSupportLevel", message.Price);
|
||||
}
|
||||
if ((res & TradingMode.TryingFallFromSupportLevel) == TradingMode.TryingFallFromSupportLevel)
|
||||
{
|
||||
await _tradeDataProvider.LogPrice(message, "TryingFallFromSupportLevel", message.Price);
|
||||
}
|
||||
|
||||
if ((res & TradingMode.InSupportLevel) == TradingMode.InSupportLevel)
|
||||
{
|
||||
await _tradeDataProvider.LogPrice(message, "InSupportLevel", message.Price);
|
||||
}
|
||||
if ((res & TradingMode.Growing) == TradingMode.Growing)
|
||||
{
|
||||
await _tradeDataProvider.LogPrice(message, "InSupportLevelGrowing", message.Price);
|
||||
}
|
||||
if ((res & TradingMode.Falling) == TradingMode.Falling)
|
||||
{
|
||||
await _tradeDataProvider.LogPrice(message, "InSupportLevelGrowingFalling", message.Price);
|
||||
}
|
||||
if ((res & TradingMode.Bezpont) == TradingMode.Bezpont)
|
||||
{
|
||||
var data = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, TimeSpan.FromMinutes(30), selector: (i) => i.Direction == 1);
|
||||
|
||||
if (data.Any() && (data.Max(d => d.Price) - data.Min(d => d.Price)) < 4)
|
||||
{
|
||||
await _tradeDataProvider.LogPrice(message, "Bezpont", message.Price);
|
||||
}
|
||||
else
|
||||
{
|
||||
res |= ~TradingMode.Bezpont;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private async Task<ImmutableDictionary<TradingEvent, decimal>> CalcTimeWindowAverageValue(ITradeDataItem message)
|
||||
private async Task<TradingMode> CalcTradingMode(ITradeDataItem message, TimeSpan period, decimal meanfullValue)
|
||||
{
|
||||
var res = TradingMode.None;
|
||||
|
||||
var data = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, period);
|
||||
if (LocalTrends.TryCalcTrendDiff(data, out var diff))
|
||||
{
|
||||
var items = data.Where(d => d.AttachedInfo != null).ToArray();
|
||||
var itemsInSupportLevels = (decimal)items.Count(i => i.AttachedInfo?.Key == Constants.PriceIsInSupportLevel);
|
||||
var itemsHigherThenSupportLevel = (decimal)items.Count(i => i.AttachedInfo?.Key == Constants.PriceIsNotInSupportLevel
|
||||
&& (i.AttachedInfo?.Value2 < i.Price));
|
||||
var itemsLowerThenSupportLevel = (decimal)items.Count(i => i.AttachedInfo?.Key == Constants.PriceIsNotInSupportLevel
|
||||
&& (i.AttachedInfo?.Value1 > i.Price));
|
||||
|
||||
if (items.Length > 0)
|
||||
{
|
||||
var itemsInSupportLevelsRel = itemsInSupportLevels / items.Length;
|
||||
var itemsHigherThenSupportLevelRel = itemsHigherThenSupportLevel / items.Length;
|
||||
var itemsLowerThenSupportLevelRel = itemsLowerThenSupportLevel / items.Length;
|
||||
|
||||
if (itemsInSupportLevelsRel > 0.7m && message?.AttachedInfo?.Key == Constants.PriceIsInSupportLevel)
|
||||
{
|
||||
res |= TradingMode.InSupportLevel;
|
||||
if (itemsHigherThenSupportLevelRel > 0.05m && (itemsLowerThenSupportLevelRel == 0 || itemsHigherThenSupportLevelRel / itemsLowerThenSupportLevelRel > 2))
|
||||
{
|
||||
res |= TradingMode.TryingGrowFromSupportLevel;
|
||||
}
|
||||
if (itemsLowerThenSupportLevelRel > 0.05m && (itemsHigherThenSupportLevelRel == 0 || itemsLowerThenSupportLevelRel / itemsHigherThenSupportLevelRel > 2))
|
||||
{
|
||||
res |= TradingMode.TryingGrowFromSupportLevel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (diff > meanfullValue)
|
||||
{
|
||||
res |= TradingMode.Growing;
|
||||
}
|
||||
if (diff < -meanfullValue)
|
||||
{
|
||||
res |= TradingMode.Falling;
|
||||
}
|
||||
if (itemsInSupportLevelsRel > 0.8m && message?.AttachedInfo?.Key == Constants.PriceIsInSupportLevel &&
|
||||
System.Math.Abs(diff) < 1.5m * meanfullValue)
|
||||
{
|
||||
res |= TradingMode.Bezpont;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private async Task<ImmutableDictionary<TradingEvent, decimal>> CalcTimeWindowAverageValue(ITradeDataItem message, bool calcOpens = false)
|
||||
{
|
||||
var res = TraderUtils.GetInitDict(Constants.BlockingCoefficient);
|
||||
var cacheSize = TimeSpan.FromSeconds(60 * 60);
|
||||
var data = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, cacheSize, selector: (i) => i.Direction == 1);
|
||||
|
||||
if (calcOpens)
|
||||
{
|
||||
var re = MovingAverage.CheckByWindowAverageMean2(data, 100, 15, 300, -2m, 2m);
|
||||
|
||||
if ((re.events & TradingEvent.OpenShort) == TradingEvent.OpenShort)
|
||||
{
|
||||
res[TradingEvent.OpenShort] = Constants.PowerUppingCoefficient;
|
||||
}
|
||||
if ((re.events & TradingEvent.OpenLong) == TradingEvent.OpenLong)
|
||||
{
|
||||
res[TradingEvent.OpenLong] = Constants.PowerUppingCoefficient;
|
||||
}
|
||||
}
|
||||
|
||||
var closings = MovingAverage.CheckByWindowAverageMean2(data, data.Length, 15, 300, -5m, 5m);
|
||||
//var re = MovingAverage.CheckByWindowAverageMean2(data, 100, 15, 300, -4m, 4m);
|
||||
if (closings.smallWindowAv != 0)
|
||||
{
|
||||
await _tradeDataProvider.LogPrice(message, "maw_small", closings.smallWindowAv);
|
||||
await _tradeDataProvider.LogPrice(message, "maw_big", closings.bigWindowAv);
|
||||
}
|
||||
//if ((re.events & TradingEvent.OpenShort) == TradingEvent.OpenShort)
|
||||
//{
|
||||
// res[TradingEvent.OpenShort] = Constants.PowerUppingCoefficient;
|
||||
//}
|
||||
//if ((re.events & TradingEvent.OpenLong) == TradingEvent.OpenLong)
|
||||
//{
|
||||
// res[TradingEvent.OpenLong] = Constants.PowerUppingCoefficient;
|
||||
//}
|
||||
if ((closings.events & TradingEvent.CloseShort) == TradingEvent.CloseShort)
|
||||
{
|
||||
res[TradingEvent.CloseShort] = Constants.PowerUppingCoefficient;
|
||||
|
@ -227,6 +350,23 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
return res.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
private ImmutableDictionary<TradingEvent, decimal> ProcessTradingMode(TradingMode mode)
|
||||
{
|
||||
var res = TraderUtils.GetInitDict(1);
|
||||
if ((mode & TradingMode.Growing) == TradingMode.Growing)
|
||||
{
|
||||
res[TradingEvent.OpenShort] = Constants.BlockingCoefficient;
|
||||
res[TradingEvent.OpenLong] = Constants.UppingCoefficient;
|
||||
}
|
||||
if ((mode & TradingMode.Falling) == TradingMode.Growing)
|
||||
{
|
||||
res[TradingEvent.OpenLong] = Constants.BlockingCoefficient;
|
||||
res[TradingEvent.OpenShort] = Constants.UppingCoefficient;
|
||||
}
|
||||
|
||||
return res.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
private ImmutableDictionary<TradingEvent, decimal> ProcessPirson(PirsonCalculatingResult pirson, ITradeDataItem message)
|
||||
{
|
||||
var res = TraderUtils.GetInitDict(Constants.BlockingCoefficient);
|
||||
|
@ -244,6 +384,28 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
|
||||
|
||||
if (pirson.Pirson > 0.5m && pirson.Pirson < 0.8m && (pirson.Pirson - olddpirs > 0.05m) && pirson.PriceDiff > 0 && (pirson.TradesDiffRelative > 0.25m))
|
||||
{
|
||||
res[TradingEvent.OpenLong] = Constants.PowerUppingCoefficient;
|
||||
}
|
||||
|
||||
if (pirson.Pirson < -0.5m && pirson.Pirson > -0.8m && (pirson.Pirson - olddpirs < -0.05m) && pirson.PriceDiff < 0 && (pirson.TradesDiffRelative > 0.25m))
|
||||
{
|
||||
res[TradingEvent.OpenShort] = Constants.PowerUppingCoefficient;
|
||||
}
|
||||
|
||||
//if (pirson.Pirson > 0.7m && (pirson.Pirson > olddpirs) && pirson.PriceDiff > 0 && (pirson.TradesDiffRelative > 0.25m))
|
||||
//{
|
||||
// res[TradingEvent.OpenLong] = Constants.UppingCoefficient;
|
||||
//}
|
||||
|
||||
//if (pirson.Pirson < -0.7m && (pirson.Pirson < olddpirs) && pirson.PriceDiff < 0 && (pirson.TradesDiffRelative > 0.25m))
|
||||
//{
|
||||
// res[TradingEvent.OpenShort] = Constants.UppingCoefficient;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
if (olddpirs > 0.9m && pirson.Pirson <= 0.9m && pirson.TradesDiffRelative < -0.1m && pirson.TradesDiff <= 0)
|
||||
{
|
||||
res[TradingEvent.CloseLong] = Constants.PowerUppingCoefficient;
|
||||
|
@ -318,8 +480,16 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
var state = ExchangeScheduler.GetCurrentState(message.Time);
|
||||
if (!message.IsHistoricalData && state == ExchangeState.ClearingTime)
|
||||
{
|
||||
if (_marginCloses.TryGetValue(string.Empty, out var time))
|
||||
{
|
||||
if (message.Time - time < TimeSpan.FromHours(2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
var futuresFigis = _portfolioWrapper.Accounts.Values.SelectMany(v => v.Assets.Values.Where(a => a.Type == AssetType.Futures)).ToArray();
|
||||
await ClosePositions(futuresFigis, message, false);
|
||||
_marginCloses[string.Empty] = message.Time;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,7 +662,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
var closingResult = await _portfolioWrapper.Accounts[asset.AccountId].ClosePosition(message.Figi);
|
||||
if (closingResult.Success)
|
||||
{
|
||||
var profitText = profit == 0 ? string.Empty : ", профит {profit}";
|
||||
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
|
||||
|
@ -543,7 +713,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
private async Task ExecuteDeclisions(ImmutableDictionary<TradingEvent, decimal> result, ITradeDataItem message, Stops st, int accountsForOpening = 1)
|
||||
{
|
||||
var state = ExchangeScheduler.GetCurrentState(message.Time);
|
||||
if (result[TradingEvent.OpenLong] >= Constants.UppingCoefficient
|
||||
if (result[TradingEvent.OpenLong] > Constants.UppingCoefficient
|
||||
&& state == ExchangeState.Open
|
||||
)
|
||||
{
|
||||
|
@ -565,7 +735,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
//await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, valHigh, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message);
|
||||
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, valLow, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message);
|
||||
}
|
||||
if (result[TradingEvent.OpenShort] >= Constants.UppingCoefficient
|
||||
if (result[TradingEvent.OpenShort] > Constants.UppingCoefficient
|
||||
&& state == ExchangeState.Open
|
||||
)
|
||||
{
|
||||
|
@ -680,12 +850,15 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
if (message.Price > nearestLevel.HighValue)
|
||||
{
|
||||
longStopLossShift = message.Price - nearestLevel.HighValue + additionalShift;
|
||||
shortStopLossShift = message.Price - nearestLevel.HighValue + additionalShift;
|
||||
}
|
||||
|
||||
nearestLevel = levelsByDiffForShort[0];
|
||||
if (message.Price < nearestLevel.LowValue)
|
||||
{
|
||||
shortStopLossShift = nearestLevel.LowValue - message.Price + additionalShift;
|
||||
longStopLossShift = nearestLevel.LowValue - message.Price + additionalShift;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -729,6 +902,13 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
var levelByTime = levelsByTime[0];
|
||||
if (message.Price >= levelByTime.LowValue && message.Price < levelByTime.HighValue)
|
||||
{
|
||||
var info = new AttachedInfo()
|
||||
{
|
||||
Key = Constants.PriceIsInSupportLevel,
|
||||
Value1 = levelByTime.LowValue,
|
||||
Value2 = levelByTime.HighValue,
|
||||
};
|
||||
message.SetAttachedInfo(info);
|
||||
if (message.Price > levelByTime.Value)
|
||||
{
|
||||
res[TradingEvent.OpenLong] = Constants.BlockingCoefficient;
|
||||
|
@ -763,35 +943,46 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
|
||||
}
|
||||
}
|
||||
else if (_oldItems.TryGetValue(message.Figi, out var old))
|
||||
else
|
||||
{
|
||||
if (old.Price >= levelByTime.LowValue && old.Price < levelByTime.HighValue)
|
||||
var info = new AttachedInfo()
|
||||
{
|
||||
var islevelUsed = false;
|
||||
if (_usedSupportLevels.TryGetValue(message.Figi, out var time))
|
||||
Key = Constants.PriceIsNotInSupportLevel,
|
||||
Value1 = levelByTime.LowValue,
|
||||
Value2 = levelByTime.HighValue,
|
||||
};
|
||||
message.SetAttachedInfo(info);
|
||||
if (_oldItems.TryGetValue(message.Figi, out var old))
|
||||
{
|
||||
if (old.Price >= levelByTime.LowValue && old.Price < levelByTime.HighValue)
|
||||
{
|
||||
if (time == levelByTime.CalculatedAt)
|
||||
var islevelUsed = false;
|
||||
if (_usedSupportLevels.TryGetValue(message.Figi, out var time))
|
||||
{
|
||||
islevelUsed = true;
|
||||
if (time == levelByTime.CalculatedAt)
|
||||
{
|
||||
islevelUsed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!islevelUsed)
|
||||
{
|
||||
if (message.Price < levelByTime.LowValue)
|
||||
if (!islevelUsed)
|
||||
{
|
||||
res[TradingEvent.OpenShort] = Constants.ForceExecuteCoefficient;
|
||||
res[TradingEvent.OpenLong] = Constants.ForceExecuteCoefficient;
|
||||
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
|
||||
}
|
||||
else if (message.Price > levelByTime.HighValue)
|
||||
{
|
||||
res[TradingEvent.OpenShort] = Constants.ForceExecuteCoefficient;
|
||||
res[TradingEvent.OpenLong] = Constants.ForceExecuteCoefficient;
|
||||
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
|
||||
if (message.Price < levelByTime.LowValue)
|
||||
{
|
||||
res[TradingEvent.OpenShort] = Constants.UppingCoefficient;
|
||||
res[TradingEvent.OpenLong] = Constants.UppingCoefficient;
|
||||
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
|
||||
}
|
||||
else if (message.Price > levelByTime.HighValue)
|
||||
{
|
||||
res[TradingEvent.OpenShort] = Constants.UppingCoefficient;
|
||||
res[TradingEvent.OpenLong] = Constants.UppingCoefficient;
|
||||
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return res.ToImmutableDictionary();
|
||||
|
|
|
@ -89,23 +89,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
return ValueTask.FromResult(Array.Empty<ITradeDataItem>());
|
||||
}
|
||||
|
||||
public ValueTask<ITradeDataItem[]> GetDataFrom20SecondsWindowCache2(string figi, string key)
|
||||
{
|
||||
return GetDataForTimeWindow(figi, TimeSpan.FromSeconds(20), key);
|
||||
}
|
||||
|
||||
public ValueTask<ITradeDataItem[]> GetDataFrom1MinuteWindowCache2(string figi, string key)
|
||||
{
|
||||
return GetDataForTimeWindow(figi, TimeSpan.FromSeconds(60), key);
|
||||
}
|
||||
public ValueTask<ITradeDataItem[]> GetDataFrom5MinuteWindowCache2(string figi, string key)
|
||||
{
|
||||
return GetDataForTimeWindow(figi, TimeSpan.FromMinutes(5), key);
|
||||
}
|
||||
public ValueTask<ITradeDataItem[]> GetDataFrom15MinuteWindowCache2(string figi, string key)
|
||||
{
|
||||
return GetDataForTimeWindow(figi, TimeSpan.FromMinutes(15), key);
|
||||
}
|
||||
public async ValueTask AddOrderbook(IOrderbook orderbook)
|
||||
{
|
||||
if (!_historyCash3.TryGetValue(orderbook.Figi, out var unit))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using KLHZ.Trader.Core.Exchange.Models.Trading;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Trading.Enums;
|
||||
|
||||
namespace KLHZ.Trader.Core.Exchange.Utils
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue