обновление стратегии
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 KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace KLHZ.Trader.Core.Contracts.Messaging.Dtos
|
namespace KLHZ.Trader.Core.Contracts.Messaging.Dtos
|
||||||
{
|
{
|
||||||
|
@ -13,5 +14,27 @@ namespace KLHZ.Trader.Core.Contracts.Messaging.Dtos
|
||||||
public int Direction { get; set; }
|
public int Direction { get; set; }
|
||||||
public decimal Value { get; init; }
|
public decimal Value { get; init; }
|
||||||
public decimal Value2 { 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.Declisions.Dtos.Enums;
|
||||||
|
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||||
using MathNet.Numerics;
|
using MathNet.Numerics;
|
||||||
|
|
||||||
namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||||||
|
@ -116,5 +117,34 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||||||
return true;
|
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;
|
using KLHZ.Trader.Core.Exchange.Utils;
|
||||||
|
|
||||||
namespace KLHZ.Trader.Core.Tests
|
namespace KLHZ.Trader.Core.Tests
|
||||||
|
|
|
@ -7,8 +7,6 @@ namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
||||||
[Table("price_changes")]
|
[Table("price_changes")]
|
||||||
public class PriceChange : ITradeDataItem
|
public class PriceChange : ITradeDataItem
|
||||||
{
|
{
|
||||||
private readonly object _locker = new();
|
|
||||||
|
|
||||||
[Column("id")]
|
[Column("id")]
|
||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
@ -59,5 +57,6 @@ namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
||||||
}
|
}
|
||||||
|
|
||||||
private AttachedInfo? _attachedInfo;
|
private AttachedInfo? _attachedInfo;
|
||||||
|
private readonly object _locker = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,14 @@
|
||||||
{
|
{
|
||||||
internal static class Constants
|
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 ForceExecuteCoefficient = 500000m;
|
||||||
internal const decimal PowerUppingCoefficient = 1.69m;
|
internal const decimal PowerUppingCoefficient = 1.69m;
|
||||||
internal const decimal UppingCoefficient = 1.3m;
|
internal const decimal UppingCoefficient = 1.3m;
|
||||||
internal const decimal LowingCoefficient = .76m;
|
internal const decimal LowingCoefficient = .76m;
|
||||||
internal const decimal PowerLowingCoefficient = .59m;
|
internal const decimal PowerLowingCoefficient = .59m;
|
||||||
internal const decimal BlockingCoefficient = 0.01m;
|
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
|
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.AssetsAccounting;
|
||||||
using KLHZ.Trader.Core.Exchange.Models.Configs;
|
using KLHZ.Trader.Core.Exchange.Models.Configs;
|
||||||
using KLHZ.Trader.Core.Exchange.Models.Trading;
|
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.Exchange.Utils;
|
||||||
using KLHZ.Trader.Core.Math.Declisions.Utils;
|
using KLHZ.Trader.Core.Math.Declisions.Utils;
|
||||||
using Microsoft.EntityFrameworkCore;
|
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, LinkedList<SupportLevel[]>> SupportLevelsHistory = new();
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, DateTime> _supportLevelsCalculationTimes = 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> _usedSupportLevels = new();
|
||||||
private readonly ConcurrentDictionary<string, DateTime> _usedSupportLevelsForClosing = new();
|
private readonly ConcurrentDictionary<string, DateTime> _usedSupportLevelsForClosing = new();
|
||||||
private readonly ConcurrentDictionary<string, ITradeDataItem> _oldItems = new();
|
private readonly ConcurrentDictionary<string, ITradeDataItem> _oldItems = new();
|
||||||
|
@ -169,52 +171,173 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
{
|
{
|
||||||
if (message.Figi == "FUTIMOEXF000")
|
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);
|
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);
|
else
|
||||||
//var mavRes = await CalcTimeWindowAverageValue(message);
|
{
|
||||||
|
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 res = TraderUtils.MergeResultsMult(declisionPirson, processSupportLevelsRes);
|
||||||
//var declisionsStops = ProcessStops(stops, 2m);
|
res = TraderUtils.MergeResultsMult(res, declisionsStops);
|
||||||
|
res = TraderUtils.MergeResultsMult(res, tradingModeResult);
|
||||||
|
res = TraderUtils.MergeResultsMax(res, mavRes);
|
||||||
|
|
||||||
|
await ExecuteDeclisions(res.ToImmutableDictionary(), message, stops, 1);
|
||||||
//var res = TraderUtils.MergeResultsMult(declisionPirson, declisionsSupportLevels);
|
}
|
||||||
//res = TraderUtils.MergeResultsMult(res, declisionsStops);
|
|
||||||
//res = TraderUtils.MergeResultsMax(res, mavRes);
|
|
||||||
|
|
||||||
//await ExecuteDeclisions(res.ToImmutableDictionary(), message, stops, 1);
|
|
||||||
_oldItems[message.Figi] = message;
|
_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 res = TraderUtils.GetInitDict(Constants.BlockingCoefficient);
|
||||||
var cacheSize = TimeSpan.FromSeconds(60 * 60);
|
var cacheSize = TimeSpan.FromSeconds(60 * 60);
|
||||||
var data = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, cacheSize, selector: (i) => i.Direction == 1);
|
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 closings = MovingAverage.CheckByWindowAverageMean2(data, data.Length, 15, 300, -5m, 5m);
|
||||||
//var re = MovingAverage.CheckByWindowAverageMean2(data, 100, 15, 300, -4m, 4m);
|
|
||||||
if (closings.smallWindowAv != 0)
|
if (closings.smallWindowAv != 0)
|
||||||
{
|
{
|
||||||
await _tradeDataProvider.LogPrice(message, "maw_small", closings.smallWindowAv);
|
await _tradeDataProvider.LogPrice(message, "maw_small", closings.smallWindowAv);
|
||||||
await _tradeDataProvider.LogPrice(message, "maw_big", closings.bigWindowAv);
|
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)
|
if ((closings.events & TradingEvent.CloseShort) == TradingEvent.CloseShort)
|
||||||
{
|
{
|
||||||
res[TradingEvent.CloseShort] = Constants.PowerUppingCoefficient;
|
res[TradingEvent.CloseShort] = Constants.PowerUppingCoefficient;
|
||||||
|
@ -227,6 +350,23 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
return res.ToImmutableDictionary();
|
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)
|
private ImmutableDictionary<TradingEvent, decimal> ProcessPirson(PirsonCalculatingResult pirson, ITradeDataItem message)
|
||||||
{
|
{
|
||||||
var res = TraderUtils.GetInitDict(Constants.BlockingCoefficient);
|
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)
|
if (olddpirs > 0.9m && pirson.Pirson <= 0.9m && pirson.TradesDiffRelative < -0.1m && pirson.TradesDiff <= 0)
|
||||||
{
|
{
|
||||||
res[TradingEvent.CloseLong] = Constants.PowerUppingCoefficient;
|
res[TradingEvent.CloseLong] = Constants.PowerUppingCoefficient;
|
||||||
|
@ -318,8 +480,16 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
var state = ExchangeScheduler.GetCurrentState(message.Time);
|
var state = ExchangeScheduler.GetCurrentState(message.Time);
|
||||||
if (!message.IsHistoricalData && state == ExchangeState.ClearingTime)
|
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();
|
var futuresFigis = _portfolioWrapper.Accounts.Values.SelectMany(v => v.Assets.Values.Where(a => a.Type == AssetType.Futures)).ToArray();
|
||||||
await ClosePositions(futuresFigis, message, false);
|
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);
|
var closingResult = await _portfolioWrapper.Accounts[asset.AccountId].ClosePosition(message.Figi);
|
||||||
if (closingResult.Success)
|
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;
|
mess = $"Закрываю позицию {asset.Figi} ({(asset.Count > 0 ? "лонг" : "шорт")}) на счёте {_portfolioWrapper.Accounts[asset.AccountId].AccountName}. Количество {(long)asset.Count}, цена ~{closingResult.ExecutedPrice / (settings?.PointPriceRub ?? 1)}, комиссия {closingResult.Comission}" + profitText;
|
||||||
}
|
}
|
||||||
else
|
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)
|
private async Task ExecuteDeclisions(ImmutableDictionary<TradingEvent, decimal> result, ITradeDataItem message, Stops st, int accountsForOpening = 1)
|
||||||
{
|
{
|
||||||
var state = ExchangeScheduler.GetCurrentState(message.Time);
|
var state = ExchangeScheduler.GetCurrentState(message.Time);
|
||||||
if (result[TradingEvent.OpenLong] >= Constants.UppingCoefficient
|
if (result[TradingEvent.OpenLong] > Constants.UppingCoefficient
|
||||||
&& state == ExchangeState.Open
|
&& 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, valHigh, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message);
|
||||||
await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, valLow, 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
|
&& state == ExchangeState.Open
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -680,12 +850,15 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
if (message.Price > nearestLevel.HighValue)
|
if (message.Price > nearestLevel.HighValue)
|
||||||
{
|
{
|
||||||
longStopLossShift = message.Price - nearestLevel.HighValue + additionalShift;
|
longStopLossShift = message.Price - nearestLevel.HighValue + additionalShift;
|
||||||
|
shortStopLossShift = message.Price - nearestLevel.HighValue + additionalShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
nearestLevel = levelsByDiffForShort[0];
|
nearestLevel = levelsByDiffForShort[0];
|
||||||
if (message.Price < nearestLevel.LowValue)
|
if (message.Price < nearestLevel.LowValue)
|
||||||
{
|
{
|
||||||
shortStopLossShift = nearestLevel.LowValue - message.Price + additionalShift;
|
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];
|
var levelByTime = levelsByTime[0];
|
||||||
if (message.Price >= levelByTime.LowValue && message.Price < levelByTime.HighValue)
|
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)
|
if (message.Price > levelByTime.Value)
|
||||||
{
|
{
|
||||||
res[TradingEvent.OpenLong] = Constants.BlockingCoefficient;
|
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;
|
Key = Constants.PriceIsNotInSupportLevel,
|
||||||
if (_usedSupportLevels.TryGetValue(message.Figi, out var time))
|
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 (!islevelUsed)
|
|
||||||
{
|
|
||||||
if (message.Price < levelByTime.LowValue)
|
|
||||||
{
|
{
|
||||||
res[TradingEvent.OpenShort] = Constants.ForceExecuteCoefficient;
|
if (message.Price < levelByTime.LowValue)
|
||||||
res[TradingEvent.OpenLong] = Constants.ForceExecuteCoefficient;
|
{
|
||||||
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
|
res[TradingEvent.OpenShort] = Constants.UppingCoefficient;
|
||||||
}
|
res[TradingEvent.OpenLong] = Constants.UppingCoefficient;
|
||||||
else if (message.Price > levelByTime.HighValue)
|
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
|
||||||
{
|
}
|
||||||
res[TradingEvent.OpenShort] = Constants.ForceExecuteCoefficient;
|
else if (message.Price > levelByTime.HighValue)
|
||||||
res[TradingEvent.OpenLong] = Constants.ForceExecuteCoefficient;
|
{
|
||||||
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
|
res[TradingEvent.OpenShort] = Constants.UppingCoefficient;
|
||||||
|
res[TradingEvent.OpenLong] = Constants.UppingCoefficient;
|
||||||
|
_usedSupportLevels[message.Figi] = levelByTime.CalculatedAt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res.ToImmutableDictionary();
|
return res.ToImmutableDictionary();
|
||||||
|
|
|
@ -89,23 +89,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
return ValueTask.FromResult(Array.Empty<ITradeDataItem>());
|
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)
|
public async ValueTask AddOrderbook(IOrderbook orderbook)
|
||||||
{
|
{
|
||||||
if (!_historyCash3.TryGetValue(orderbook.Figi, out var unit))
|
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
|
namespace KLHZ.Trader.Core.Exchange.Utils
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue