Compare commits
4 Commits
270e807591
...
6884407f12
Author | SHA1 | Date |
---|---|---|
|
6884407f12 | |
|
d0786cfe19 | |
|
fbd3da2b8d | |
|
ff1090c819 |
|
@ -5,13 +5,13 @@
|
|||
public readonly int Start;
|
||||
public readonly int Bound;
|
||||
public readonly int End;
|
||||
public readonly float DiffStart;
|
||||
public readonly float DiffEnd;
|
||||
public readonly decimal DiffStart;
|
||||
public readonly decimal DiffEnd;
|
||||
public readonly bool Success;
|
||||
public readonly TimeSpan PeriodStart;
|
||||
public readonly TimeSpan PeriodEnd;
|
||||
|
||||
public TwoPeriodsResultDto(bool success, float diffStart, float diffEnd, int start, int bound, int end,
|
||||
public TwoPeriodsResultDto(bool success, decimal diffStart, decimal diffEnd, int start, int bound, int end,
|
||||
TimeSpan periodStart, TimeSpan periodEnd)
|
||||
{
|
||||
Success = success;
|
||||
|
|
|
@ -7,9 +7,17 @@ namespace KLHZ.Trader.Core.Contracts.Declisions.Interfaces
|
|||
public string Figi { get; }
|
||||
public int Length { get; }
|
||||
public ValueTask AddData(INewPrice priceChange);
|
||||
public ValueTask<(DateTime[] timestamps, float[] prices)> GetData();
|
||||
public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData();
|
||||
public ValueTask AddOrderbook(IOrderbook orderbook);
|
||||
|
||||
/// <summary>
|
||||
/// Число заявок на продаже в стакане.
|
||||
/// </summary>
|
||||
public decimal AsksCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Число заявок на покупку в стакане.
|
||||
/// </summary>
|
||||
public decimal BidsCount { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
public static class Lines
|
||||
{
|
||||
public static (float x, float y) LinesCrossing(float k1, float b1, float k2, float b2)
|
||||
public static (decimal x, decimal y) LinesCrossing(decimal k1, decimal b1, decimal k2, decimal b2)
|
||||
{
|
||||
var x = (b2 - b1) / (k1 - k2);
|
||||
var y = k1 * x + b1;
|
||||
|
@ -10,10 +10,10 @@
|
|||
return (x, y);
|
||||
}
|
||||
|
||||
public static bool IsLinesCrossing(DateTime time1, DateTime time2, float val1_1, float val1_2, float val2_1, float val2_2)
|
||||
public static bool IsLinesCrossing(DateTime time1, DateTime time2, decimal val1_1, decimal val1_2, decimal val2_1, decimal val2_2)
|
||||
{
|
||||
var dtime = (float)(time2 - time1).TotalSeconds;
|
||||
|
||||
var dtime = (decimal)(time2 - time1).TotalSeconds;
|
||||
if (dtime == 0) return false;
|
||||
var dval1 = val1_2 - val1_1;
|
||||
var k1 = dval1 / dtime;
|
||||
var b1 = val1_1;
|
||||
|
@ -25,9 +25,12 @@
|
|||
if (k1 != k2)
|
||||
{
|
||||
var cross = LinesCrossing(k1, b1, k2, b2);
|
||||
var crossingTimestamp = time1.AddSeconds(cross.x);
|
||||
if (cross.x>=0 && cross.x <= dtime)
|
||||
{
|
||||
var crossingTimestamp = time1.AddSeconds((double)cross.x);
|
||||
return crossingTimestamp >= time1 && crossingTimestamp <= time2;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
{
|
||||
public readonly int Start;
|
||||
public readonly int End;
|
||||
public readonly float LastPrice;
|
||||
public readonly float FirstPrice;
|
||||
public readonly float PeriodDiff;
|
||||
public readonly float PeriodMax;
|
||||
public readonly float PeriodMin;
|
||||
public readonly decimal LastPrice;
|
||||
public readonly decimal FirstPrice;
|
||||
public readonly decimal PeriodDiff;
|
||||
public readonly decimal PeriodMax;
|
||||
public readonly decimal PeriodMin;
|
||||
public readonly bool Success;
|
||||
public readonly TimeSpan Period;
|
||||
|
||||
public PeriodPricesInfoDto(bool success, float firstPrice, float lastPrice, float periodDiff, float periodMin, float periodMax, TimeSpan period, int start, int end)
|
||||
public PeriodPricesInfoDto(bool success, decimal firstPrice, decimal lastPrice, decimal periodDiff, decimal periodMin, decimal periodMax, TimeSpan period, int start, int end)
|
||||
{
|
||||
Success = success;
|
||||
LastPrice = lastPrice;
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
|||
public decimal BidsCount => 1;
|
||||
|
||||
private readonly object _locker = new();
|
||||
private readonly float[] Prices = new float[CacheMaxLength];
|
||||
private readonly decimal[] Prices = new decimal[CacheMaxLength];
|
||||
private readonly DateTime[] Timestamps = new DateTime[CacheMaxLength];
|
||||
|
||||
private int _length = 0;
|
||||
|
@ -36,7 +36,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
|||
Array.Copy(Prices, 1, Prices, 0, Prices.Length - 1);
|
||||
Array.Copy(Timestamps, 1, Timestamps, 0, Timestamps.Length - 1);
|
||||
|
||||
Prices[Prices.Length - 1] = (float)priceChange.Value;
|
||||
Prices[Prices.Length - 1] = priceChange.Value;
|
||||
Timestamps[Timestamps.Length - 1] = priceChange.Time;
|
||||
|
||||
if (_length < CacheMaxLength)
|
||||
|
@ -47,11 +47,11 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
|||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
public ValueTask<(DateTime[] timestamps, float[] prices)> GetData()
|
||||
public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData()
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
var prices = new float[_length];
|
||||
var prices = new decimal[_length];
|
||||
var timestamps = new DateTime[_length];
|
||||
Array.Copy(Prices, Prices.Length - _length, prices, 0, prices.Length);
|
||||
Array.Copy(Timestamps, Prices.Length - _length, timestamps, 0, timestamps.Length);
|
||||
|
@ -79,7 +79,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
|||
.Skip(priceChanges.Length - CacheMaxLength)
|
||||
.ToArray();
|
||||
var prices = selectedPriceChanges
|
||||
.Select(pc => (float)pc.Value)
|
||||
.Select(pc => pc.Value)
|
||||
.ToArray();
|
||||
var times = selectedPriceChanges
|
||||
.Select(pc => pc.Time)
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
|||
}
|
||||
|
||||
private readonly object _locker = new();
|
||||
private readonly float[] Prices = new float[_arrayMaxLength];
|
||||
private readonly decimal[] Prices = new decimal[_arrayMaxLength];
|
||||
private readonly DateTime[] Timestamps = new DateTime[_arrayMaxLength];
|
||||
|
||||
private int _length = 0;
|
||||
|
@ -59,7 +59,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
|||
lock (_locker)
|
||||
{
|
||||
_pointer++;
|
||||
Prices[_pointer] = (float)priceChange.Value;
|
||||
Prices[_pointer] = priceChange.Value;
|
||||
Timestamps[_pointer] = priceChange.Time;
|
||||
if (_length < CacheMaxLength)
|
||||
{
|
||||
|
@ -76,17 +76,17 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
|||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
public ValueTask<(DateTime[] timestamps, float[] prices)> GetData()
|
||||
public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData()
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_pointer < 0)
|
||||
{
|
||||
return ValueTask.FromResult((Array.Empty<DateTime>(), Array.Empty<float>()));
|
||||
return ValueTask.FromResult((Array.Empty<DateTime>(), Array.Empty<decimal>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
var prices = new float[_length];
|
||||
var prices = new decimal[_length];
|
||||
var timestamps = new DateTime[_length];
|
||||
Array.Copy(Prices, 1 + _pointer - _length, prices, 0, prices.Length);
|
||||
Array.Copy(Timestamps, 1 + _pointer - _length, timestamps, 0, timestamps.Length);
|
||||
|
@ -123,7 +123,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
|||
|
||||
foreach (var pc in selectedPriceChanges)
|
||||
{
|
||||
AddData(pc);
|
||||
AddData(pc).AsTask().Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
{
|
||||
public static class MovingAverage
|
||||
{
|
||||
private static (DateTime time, float value) CalcTimeWindowAverageValue(DateTime[] timestamps, float[] values, int window, int shift = 0)
|
||||
internal static (DateTime time, decimal value) CalcTimeWindowAverageValue(DateTime[] timestamps, decimal[] values, int window, int shift = 0)
|
||||
{
|
||||
var sum = values[values.Length - 1 - shift];
|
||||
var count = 1;
|
||||
var count = 1m;
|
||||
var startTime = timestamps[timestamps.Length - 1 - shift];
|
||||
for (int i = 2; i < values.Length && startTime - timestamps[values.Length - i - shift] < TimeSpan.FromSeconds(window); i++)
|
||||
{
|
||||
|
@ -18,33 +18,44 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return (startTime, sum / count);
|
||||
}
|
||||
|
||||
public static TradingEvent CheckByWindowAverageMean(DateTime[] timestamps, float[] prices, int size, float meanfullStep = 3f)
|
||||
public static TradingEvent CheckByWindowAverageMean(DateTime[] timestamps, decimal[] prices, int size,int smallWindow, int bigWindow, decimal meanfullStep = 3m)
|
||||
{
|
||||
var twav15s = new float[size];
|
||||
var twav120s = new float[size];
|
||||
var times = new DateTime[size];
|
||||
var res = TradingEvent.None;
|
||||
if (timestamps.Length < size)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
var pricesForFinalComparison = new decimal[size];
|
||||
var twavss = new decimal[size];
|
||||
var twavbs = new decimal[size];
|
||||
var times = new DateTime[size];
|
||||
|
||||
|
||||
for (int shift = 0; shift < size; shift++)
|
||||
{
|
||||
var twav15 = CalcTimeWindowAverageValue(timestamps, prices, 15, shift);
|
||||
var twav120 = CalcTimeWindowAverageValue(timestamps, prices, 120, shift);
|
||||
twav15s[size - 1 - shift] = twav15.value;
|
||||
twav120s[size - 1 - shift] = twav120.value;
|
||||
times[size - 1 - shift] = twav120.time;
|
||||
if (System.Math.Abs(twav120.value - prices[prices.Length - 1]) > 3 * meanfullStep)
|
||||
var twavs = CalcTimeWindowAverageValue(timestamps, prices, smallWindow, shift);
|
||||
var twavb = CalcTimeWindowAverageValue(timestamps, prices, bigWindow, shift);
|
||||
pricesForFinalComparison[size - 1 - shift] = prices[prices.Length - 1 - shift];
|
||||
twavss[size - 1 - shift] = twavs.value;
|
||||
twavbs[size - 1 - shift] = twavb.value;
|
||||
times[size - 1 - shift] = twavb.time;
|
||||
if (System.Math.Abs(twavb.value - prices[prices.Length - 1]) > 2 * meanfullStep)
|
||||
{
|
||||
res |= TradingEvent.StopBuy;
|
||||
return res;
|
||||
}
|
||||
if (shift > 0)
|
||||
{
|
||||
var i1 = size - 1 - shift;
|
||||
var i2 = size - shift;
|
||||
var isCrossing = Lines.IsLinesCrossing(
|
||||
times[size - 1 - shift],
|
||||
times[size - 2 - shift],
|
||||
twav15s[size - 1 - shift],
|
||||
twav15s[size - 2 - shift],
|
||||
twav120s[size - 1 - shift],
|
||||
twav120s[size - 2 - shift]);
|
||||
times[i1],
|
||||
times[i2],
|
||||
twavss[i1],
|
||||
twavss[i2],
|
||||
twavbs[i1],
|
||||
twavbs[i2]);
|
||||
|
||||
if (shift == 1 && !isCrossing) //если нет пересечения скользящих средний с окном 120 и 15 секунд между
|
||||
//текущей и предыдущей точкой - можно не продолжать выполнение.
|
||||
{
|
||||
|
@ -53,9 +64,9 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
if (shift > 1 && isCrossing)
|
||||
{
|
||||
// если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта
|
||||
if (twav120s[size - 1] <= twav15s[size - 1] && twav120s[size - 2] > twav15s[size - 2])
|
||||
if (twavbs[size - 1] <= twavss[size - 1] && twavbs[size - 2] > twavss[size - 2])
|
||||
{
|
||||
if (twav15s[size - 1 - shift] - twav15s[size - 1] >= meanfullStep)
|
||||
if (pricesForFinalComparison[size - 1 - shift] - pricesForFinalComparison[size - 1] >= meanfullStep)
|
||||
{
|
||||
res |= TradingEvent.LongOpen;
|
||||
res |= TradingEvent.ShortClose;
|
||||
|
@ -64,9 +75,9 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
}
|
||||
|
||||
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
|
||||
if (twav15s[size - 1] <= twav120s[size - 1] && twav15s[size - 2] > twav120s[size - 2])
|
||||
if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2])
|
||||
{
|
||||
if (twav15s[size - 1 - shift] - twav15s[size - 1] <= -meanfullStep)
|
||||
if (pricesForFinalComparison[size - 1 - shift] - pricesForFinalComparison[size - 1] <= -meanfullStep)
|
||||
{
|
||||
res |= TradingEvent.LongClose;
|
||||
res |= TradingEvent.ShortOpen;
|
||||
|
|
|
@ -21,8 +21,8 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
var lastPriceTime = times[times.Length - 1];
|
||||
var intervalEnd = lastPriceTime - timeShift;
|
||||
var intervalStart = intervalEnd - timeSpan;
|
||||
var max = float.MinValue;
|
||||
var min = float.MaxValue;
|
||||
var max = decimal.MinValue;
|
||||
var min = decimal.MaxValue;
|
||||
|
||||
var intervaEndIndex = -1;
|
||||
var intervaStartIndex = -1;
|
||||
|
@ -69,18 +69,18 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return res;
|
||||
}
|
||||
|
||||
internal static bool CheckStable(this PeriodPricesInfoDto data, float meanfullDiff)
|
||||
internal static bool CheckStable(this PeriodPricesInfoDto data, decimal meanfullDiff)
|
||||
{
|
||||
meanfullDiff = System.Math.Abs(meanfullDiff);
|
||||
return data.Success && System.Math.Abs(data.PeriodDiff) < 1.5 * meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 2 * meanfullDiff;
|
||||
return data.Success && System.Math.Abs(data.PeriodDiff) < 1.5m * meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 2 * meanfullDiff;
|
||||
}
|
||||
|
||||
internal static bool CheckGrowing(this PeriodPricesInfoDto data, float meanfullDiff)
|
||||
internal static bool CheckGrowing(this PeriodPricesInfoDto data, decimal meanfullDiff)
|
||||
{
|
||||
return meanfullDiff > 0 && data.Success && data.PeriodDiff > meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 3 * System.Math.Abs(data.PeriodDiff);
|
||||
}
|
||||
|
||||
internal static bool CheckFalling(this PeriodPricesInfoDto data, float meanfullDiff)
|
||||
internal static bool CheckFalling(this PeriodPricesInfoDto data, decimal meanfullDiff)
|
||||
{
|
||||
meanfullDiff = -meanfullDiff;
|
||||
return meanfullDiff < 0 && data.Success && data.PeriodDiff < meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 3 * System.Math.Abs(data.PeriodDiff);
|
||||
|
@ -88,20 +88,20 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
|
||||
internal static float CalcTrendRelationAbs(PeriodPricesInfoDto first, PeriodPricesInfoDto second)
|
||||
{
|
||||
var k1 = System.Math.Abs(first.PeriodDiff) / System.Math.Abs(first.Period.TotalSeconds);
|
||||
var k2 = System.Math.Abs(second.PeriodDiff) / System.Math.Abs(second.Period.TotalSeconds);
|
||||
var k1 = System.Math.Abs(first.PeriodDiff) / System.Math.Abs((decimal)first.Period.TotalSeconds);
|
||||
var k2 = System.Math.Abs(second.PeriodDiff) / System.Math.Abs((decimal)second.Period.TotalSeconds);
|
||||
if (k2 == 0 && k1 != 0) return 1000;
|
||||
return (float)(k1 / k2);
|
||||
}
|
||||
internal static float CalcTrendRelationAbs(TwoPeriodsResultDto data)
|
||||
{
|
||||
var k1 = System.Math.Abs(data.DiffStart) / System.Math.Abs(data.PeriodStart.TotalSeconds);
|
||||
var k2 = System.Math.Abs(data.DiffEnd) / System.Math.Abs(data.PeriodEnd.TotalSeconds);
|
||||
var k1 = System.Math.Abs(data.DiffStart) / System.Math.Abs((decimal)data.PeriodStart.TotalSeconds);
|
||||
var k2 = System.Math.Abs(data.DiffEnd) / System.Math.Abs((decimal)data.PeriodEnd.TotalSeconds);
|
||||
if (k2 == 0 && k1 != 0) return 1000;
|
||||
return (float)(k1 / k2);
|
||||
}
|
||||
|
||||
internal static bool CheckDowntrendEnding(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff)
|
||||
internal static bool CheckDowntrendEnding(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
|
||||
{
|
||||
var totalDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, firstPeriod + secondPeriod);
|
||||
var startDiff = unit.GetPriceDiffForTimeSpan(secondPeriod, firstPeriod);
|
||||
|
@ -121,7 +121,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return res;
|
||||
}
|
||||
|
||||
internal static bool CheckUptrendEnding(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff)
|
||||
internal static bool CheckUptrendEnding(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
|
||||
{
|
||||
var totalDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, firstPeriod + secondPeriod);
|
||||
var startDiff = unit.GetPriceDiffForTimeSpan(secondPeriod, firstPeriod);
|
||||
|
@ -141,7 +141,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return res;
|
||||
}
|
||||
|
||||
internal static bool CheckDowntrendStarting(this PriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff)
|
||||
internal static bool CheckDowntrendStarting(this PriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
|
||||
{
|
||||
var totalDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, firstPeriod + secondPeriod);
|
||||
var startDiff = unit.GetPriceDiffForTimeSpan(secondPeriod, firstPeriod);
|
||||
|
@ -156,7 +156,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return totalDiff.Success && (isStartStable || isStartGrows) && isEndFalls && trendRelation >= 2;
|
||||
}
|
||||
|
||||
internal static bool CheckUptrendStarting(this PriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff)
|
||||
internal static bool CheckUptrendStarting(this PriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
|
||||
{
|
||||
var totalDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, firstPeriod + secondPeriod);
|
||||
var startDiff = unit.GetPriceDiffForTimeSpan(secondPeriod, firstPeriod);
|
||||
|
@ -185,7 +185,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return res;
|
||||
}
|
||||
|
||||
internal static TwoPeriodsResultDto GetTwoPeriodsProcessingData(this (DateTime[] timestamps, float[] prices) data, TimeSpan shift, int shiftPointsStart, int shiftPointsEnd, TimeSpan firstPeriod, float meanfullDiff)
|
||||
internal static TwoPeriodsResultDto GetTwoPeriodsProcessingData(this (DateTime[] timestamps, decimal[] prices) data, TimeSpan shift, int shiftPointsStart, int shiftPointsEnd, TimeSpan firstPeriod, decimal meanfullDiff)
|
||||
{
|
||||
var res = new TwoPeriodsResultDto(success: false, 0, 0, 0, 0, 0, TimeSpan.Zero, TimeSpan.Zero);
|
||||
var time = data.timestamps;
|
||||
|
@ -222,12 +222,12 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return res;
|
||||
}
|
||||
|
||||
public static bool CheckLongClose(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff, int pointsStart, int pointsEnd)
|
||||
public static bool CheckLongClose(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int pointsStart, int pointsEnd)
|
||||
{
|
||||
var data = unit.GetData().Result;
|
||||
var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, pointsStart, pointsEnd, firstPeriod, meanfullDiff);
|
||||
var trendRelation = CalcTrendRelationAbs(periodStat);
|
||||
var isStartOk = periodStat.Success && periodStat.DiffStart > 0 && periodStat.DiffStart > 1.5 * meanfullDiff;
|
||||
var isStartOk = periodStat.Success && periodStat.DiffStart > 0 && periodStat.DiffStart > 1.5m * meanfullDiff;
|
||||
var isEndOk = periodStat.Success && periodStat.DiffEnd < meanfullDiff;
|
||||
|
||||
if (isEndOk)
|
||||
|
@ -247,7 +247,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return isStartOk && isEndOk && data.prices[periodStat.End] - data.prices[periodStat.Start] >= meanfullDiff;
|
||||
}
|
||||
|
||||
internal static bool CheckUptrendStarting2(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff)
|
||||
internal static bool CheckUptrendStarting2(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
|
||||
{
|
||||
var data = unit.GetData().Result;
|
||||
var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, 15, 2, firstPeriod, meanfullDiff);
|
||||
|
@ -272,7 +272,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
return isStartOk && isEndOk;
|
||||
}
|
||||
|
||||
internal static bool _CheckUptrendStarting2(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff)
|
||||
internal static bool _CheckUptrendStarting2(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
|
||||
{
|
||||
var data = unit.GetData().Result;
|
||||
var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, 15, 1, firstPeriod, meanfullDiff);
|
||||
|
@ -298,7 +298,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
}
|
||||
|
||||
|
||||
public static bool CheckLongOpen(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff, int pointsStart, int pointsEnd)
|
||||
public static bool CheckLongOpen(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int pointsStart, int pointsEnd)
|
||||
{
|
||||
var data = unit.GetData().Result;
|
||||
var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, pointsStart, pointsEnd, firstPeriod, meanfullDiff);
|
||||
|
@ -325,14 +325,14 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
|
||||
public static TradingEvent Detect(IPriceHistoryCacheUnit data)
|
||||
{
|
||||
float meanfullDiff;
|
||||
decimal meanfullDiff;
|
||||
if (data.Figi == "BBG004730N88")
|
||||
{
|
||||
meanfullDiff = 0.05f;
|
||||
meanfullDiff = 0.05m;
|
||||
}
|
||||
else if (data.Figi == "FUTIMOEXF000")
|
||||
{
|
||||
meanfullDiff = 1f;
|
||||
meanfullDiff = 1m;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -352,7 +352,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
}
|
||||
//var downtrendEnds = data.CheckDowntrendEnding(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(15), meanfullDiff);
|
||||
|
||||
var uptrendEnds = data.CheckLongClose(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20), meanfullDiff * 1.5f, 8, 8);
|
||||
var uptrendEnds = data.CheckLongClose(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20), meanfullDiff * 1.5m, 8, 8);
|
||||
var uptrendEnds2 = data.CheckLongClose(TimeSpan.FromSeconds(120), TimeSpan.FromSeconds(30), meanfullDiff, 15, 8);
|
||||
uptrendEnds |= uptrendEnds2;
|
||||
if (uptrendEnds)
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var count = 1;
|
||||
var figi = "figi";
|
||||
var hist = GetHistory(count, figi);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2("", hist);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2(figi, hist);
|
||||
var data = cacheUnit.GetData().Result;
|
||||
|
||||
Assert.That(data.prices.Length == count);
|
||||
|
@ -64,7 +64,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var count = 20;
|
||||
var figi = "figi";
|
||||
var hist = GetHistory(count, figi);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2("", hist);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2(figi, hist);
|
||||
var data = cacheUnit.GetData().Result;
|
||||
|
||||
Assert.That(data.prices.Length == count);
|
||||
|
@ -83,7 +83,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var count = PriceHistoryCacheUnit.CacheMaxLength;
|
||||
var figi = "figi";
|
||||
var hist = GetHistory(count, figi);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2("", hist);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2(figi, hist);
|
||||
var data = cacheUnit.GetData().Result;
|
||||
|
||||
Assert.That(data.prices.Length == count);
|
||||
|
@ -103,7 +103,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var count = PriceHistoryCacheUnit.CacheMaxLength + shift;
|
||||
var figi = "figi";
|
||||
var hist = GetHistory(count, figi);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2("", hist);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2(figi, hist);
|
||||
var data = cacheUnit.GetData().Result;
|
||||
|
||||
Assert.That(data.prices.Length == count - shift);
|
||||
|
@ -127,7 +127,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var count = PriceHistoryCacheUnit.CacheMaxLength + shift;
|
||||
var figi = "figi";
|
||||
var hist = GetHistory(count, figi);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2("", hist);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2(figi, hist);
|
||||
var data = cacheUnit.GetData().Result;
|
||||
|
||||
Assert.That(data.prices.Length == count - shift);
|
||||
|
@ -151,7 +151,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var count = PriceHistoryCacheUnit.CacheMaxLength + shift;
|
||||
var figi = "figi";
|
||||
var hist = GetHistory(count, figi);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2("", hist);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2(figi, hist);
|
||||
var data = cacheUnit.GetData().Result;
|
||||
|
||||
Assert.That(data.prices.Length == count - shift);
|
||||
|
@ -175,7 +175,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var count = PriceHistoryCacheUnit.CacheMaxLength;
|
||||
var figi = "figi";
|
||||
var hist = GetHistory(count, figi);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2("", hist);
|
||||
var cacheUnit = new PriceHistoryCacheUnit2(figi, hist);
|
||||
var data = cacheUnit.GetData().Result;
|
||||
|
||||
Assert.That(data.prices.Length == count);
|
||||
|
@ -192,7 +192,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
cacheUnit.AddData(newData1);
|
||||
|
||||
var data2 = cacheUnit.GetData().Result;
|
||||
Assert.IsTrue(data2.prices[data2.prices.Length - 1] == (float)newData1.Value);
|
||||
Assert.IsTrue(data2.prices[data2.prices.Length - 1] == newData1.Value);
|
||||
Assert.IsTrue(data2.timestamps[data2.timestamps.Length - 1] == newData1.Time);
|
||||
|
||||
var newData2 = new PriceChange() { Figi = figi, Ticker = figi, Value = 100501, Time = DateTime.UtcNow };
|
||||
|
@ -200,7 +200,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
cacheUnit.AddData(newData2);
|
||||
|
||||
var data3 = cacheUnit.GetData().Result;
|
||||
Assert.IsTrue(data3.prices[data3.prices.Length - 1] == (float)newData2.Value);
|
||||
Assert.IsTrue(data3.prices[data3.prices.Length - 1] == newData2.Value);
|
||||
Assert.IsTrue(data3.timestamps[data3.timestamps.Length - 1] == newData2.Time);
|
||||
}
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
cacheUnit.AddData(newData1);
|
||||
|
||||
var data2 = cacheUnit.GetData().Result;
|
||||
Assert.IsTrue(data2.prices[data2.prices.Length - 1] == (float)newData1.Value);
|
||||
Assert.IsTrue(data2.prices[data2.prices.Length - 1] == newData1.Value);
|
||||
Assert.IsTrue(data2.timestamps[data2.timestamps.Length - 1] == newData1.Time);
|
||||
|
||||
var newData2 = new PriceChange() { Figi = figi, Ticker = figi, Value = 100501, Time = DateTime.UtcNow };
|
||||
|
@ -200,7 +200,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
cacheUnit.AddData(newData2);
|
||||
|
||||
var data3 = cacheUnit.GetData().Result;
|
||||
Assert.IsTrue(data3.prices[data3.prices.Length - 1] == (float)newData2.Value);
|
||||
Assert.IsTrue(data3.prices[data3.prices.Length - 1] == newData2.Value);
|
||||
Assert.IsTrue(data3.timestamps[data3.timestamps.Length - 1] == newData2.Time);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
{
|
||||
public class HistoryProcessingInstrumentsTests
|
||||
{
|
||||
private static PriceChange[] GetHistory(int count, string figi, DateTime startDt, float startValue, float step)
|
||||
private static PriceChange[] GetHistory(int count, string figi, DateTime startDt, decimal startValue, decimal step)
|
||||
{
|
||||
var res = new PriceChange[count];
|
||||
if (count != 0)
|
||||
|
@ -21,7 +21,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
Ticker = figi + "_ticker",
|
||||
Id = i,
|
||||
Time = startDt,
|
||||
Value = (decimal)startValue,
|
||||
Value = startValue,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var figi = "figi";
|
||||
var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
|
||||
var count = 100;
|
||||
var step = 0.5f;
|
||||
var step = 0.5m;
|
||||
var startValue = 10;
|
||||
var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var figi = "figi";
|
||||
var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
|
||||
var count = 100;
|
||||
var step = 0.5f;
|
||||
var step = 0.5m;
|
||||
var startValue = 10;
|
||||
|
||||
var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
|
||||
|
@ -137,7 +137,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var figi = "figi";
|
||||
var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
|
||||
var count = 100;
|
||||
var step = -0.5f;
|
||||
var step = -0.5m;
|
||||
var startValue = 10;
|
||||
|
||||
var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
|
||||
|
@ -172,7 +172,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var figi = "figi";
|
||||
var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
|
||||
var count = 100;
|
||||
var step = -0.5f;
|
||||
var step = -0.5m;
|
||||
var startValue = 10;
|
||||
|
||||
var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
|
||||
|
@ -207,7 +207,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var figi = "figi";
|
||||
var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
|
||||
var count = 100;
|
||||
var step = -0.5f;
|
||||
var step = -0.5m;
|
||||
var startValue = 10;
|
||||
|
||||
var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
|
||||
|
|
|
@ -10,11 +10,11 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var time2 = DateTime.UtcNow;
|
||||
var time1 = time2.AddSeconds(-20);
|
||||
|
||||
var val1_1 = 0.5f;
|
||||
var val1_2 = -0.5f;
|
||||
var val1_1 = 0.5m;
|
||||
var val1_2 = -0.5m;
|
||||
|
||||
var val2_1 = -0.5f;
|
||||
var val2_2 = 0.5f;
|
||||
var val2_1 = -0.5m;
|
||||
var val2_2 = 0.5m;
|
||||
|
||||
Assert.IsTrue(Lines.IsLinesCrossing(time1, time2, val1_1, val1_2, val2_1, val2_2));
|
||||
}
|
||||
|
@ -25,11 +25,11 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var time2 = DateTime.UtcNow;
|
||||
var time1 = time2.AddSeconds(-20);
|
||||
|
||||
var val1_1 = 0.5f;
|
||||
var val1_2 = -0.5f;
|
||||
var val1_1 = 0.5m;
|
||||
var val1_2 = -0.5m;
|
||||
|
||||
var val2_1 = 0.5f;
|
||||
var val2_2 = -0.5f;
|
||||
var val2_1 = 0.5m;
|
||||
var val2_2 = -0.5m;
|
||||
|
||||
Assert.IsFalse(Lines.IsLinesCrossing(time1, time2, val1_1, val1_2, val2_1, val2_2));
|
||||
}
|
||||
|
|
|
@ -142,14 +142,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
{
|
||||
SubscribeOrderBookRequest = bookRequest
|
||||
});
|
||||
using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
|
||||
var pricesBuffer = new List<PriceChange>();
|
||||
var orderbookItemsBuffer = new List<OrderbookItem>();
|
||||
var tradesBuffer = new List<InstrumentTrade>();
|
||||
var lastWriteOrderbooks = DateTime.UtcNow;
|
||||
var lastWriteTrades = DateTime.UtcNow;
|
||||
var lastWritePrices = DateTime.UtcNow;
|
||||
var lastWrite = DateTime.UtcNow;
|
||||
await foreach (var response in stream.ResponseStream.ReadAllAsync())
|
||||
{
|
||||
|
@ -214,8 +210,12 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
await _eventBus.Broadcast(message);
|
||||
}
|
||||
|
||||
if (orderbookItemsBuffer.Count + pricesBuffer.Count + tradesBuffer.Count > 1000 || (DateTime.UtcNow - lastWrite).TotalSeconds > 10)
|
||||
if (orderbookItemsBuffer.Count + pricesBuffer.Count + tradesBuffer.Count > 0 || (DateTime.UtcNow - lastWrite).TotalSeconds > 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
lastWrite = DateTime.UtcNow;
|
||||
if (orderbookItemsBuffer.Count > 0)
|
||||
{
|
||||
|
@ -234,6 +234,11 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка при сохранении данных биржи.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
_dataBus.AddChannel(nameof(Trader), _ordersbookChannel);
|
||||
_ = ProcessPrices();
|
||||
_ = ProcessOrdersbooks();
|
||||
_ = BackgroundWorker();
|
||||
}
|
||||
|
||||
private async Task InitStops()
|
||||
|
@ -119,86 +118,126 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
while (await _pricesChannel.Reader.WaitToReadAsync())
|
||||
{
|
||||
var message = await _pricesChannel.Reader.ReadAsync();
|
||||
//if (_tradingInstrumentsFigis.Contains(message.Figi))
|
||||
//{
|
||||
// if (_historyCash.TryGetValue(message.Figi, out var unit))
|
||||
// {
|
||||
// await unit.AddData(message);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// unit = new PriceHistoryCacheUnit2(message.Figi, message);
|
||||
// _historyCash.TryAdd(message.Figi, unit);
|
||||
// }
|
||||
// var data = await unit.GetData();
|
||||
// var declisionsForSave = new List<Declision>();
|
||||
// if (message.Figi == "FUTIMOEXF000")
|
||||
// {
|
||||
// var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 3f);
|
||||
// if ((result & TradingEvent.StopBuy) == TradingEvent.StopBuy)
|
||||
// {
|
||||
// var stopTo = DateTime.UtcNow.AddMinutes(_buyStopLength);
|
||||
// BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
|
||||
// declisionsForSave.Add(new Declision()
|
||||
// {
|
||||
// AccountId = string.Empty,
|
||||
// Figi = message.Figi,
|
||||
// Ticker = message.Ticker,
|
||||
// Price = message.Value,
|
||||
// Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
// Action = DeclisionTradeAction.StopBuy,
|
||||
// });
|
||||
// }
|
||||
if (_tradingInstrumentsFigis.Contains(message.Figi))
|
||||
{
|
||||
if (_historyCash.TryGetValue(message.Figi, out var unit))
|
||||
{
|
||||
await unit.AddData(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
unit = new PriceHistoryCacheUnit2(message.Figi, message);
|
||||
_historyCash.TryAdd(message.Figi, unit);
|
||||
}
|
||||
try
|
||||
{
|
||||
var data = await unit.GetData();
|
||||
var declisionsForSave = new List<Declision>();
|
||||
if (message.Figi == "FUTIMOEXF000")
|
||||
{
|
||||
if (unit.Length < 100)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if ((result & TradingEvent.LongOpen) == TradingEvent.LongOpen
|
||||
// && !BuyStops.TryGetValue(message.Figi, out _))
|
||||
// {
|
||||
// var stopTo = DateTime.UtcNow.AddMinutes(_buyStopLength);
|
||||
// BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
|
||||
// declisionsForSave.Add(new Declision()
|
||||
// {
|
||||
// AccountId = string.Empty,
|
||||
// Figi = message.Figi,
|
||||
// Ticker = message.Ticker,
|
||||
// Price = message.Value,
|
||||
// Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
// Action = DeclisionTradeAction.OpenLong,
|
||||
// });
|
||||
// }
|
||||
|
||||
// if ((result & TradingEvent.LongClose) == TradingEvent.LongClose)
|
||||
// {
|
||||
// declisionsForSave.Add(new Declision()
|
||||
// {
|
||||
// AccountId = string.Empty,
|
||||
// Figi = message.Figi,
|
||||
// Ticker = message.Ticker,
|
||||
// Price = message.Value,
|
||||
// Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
// Action = DeclisionTradeAction.CloseLong,
|
||||
// });
|
||||
// }
|
||||
var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100,15,120);
|
||||
if ((result & TradingEvent.StopBuy) == TradingEvent.StopBuy)
|
||||
{
|
||||
var stopTo = (message.IsHistoricalData?message.Time: DateTime.UtcNow).AddMinutes(_buyStopLength);
|
||||
BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
|
||||
declisionsForSave.Add(new Declision()
|
||||
{
|
||||
AccountId = string.Empty,
|
||||
Figi = message.Figi,
|
||||
Ticker = message.Ticker,
|
||||
Price = message.Value,
|
||||
Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
Action = DeclisionTradeAction.StopBuy,
|
||||
});
|
||||
}
|
||||
|
||||
// if ((result & TradingEvent.ShortOpen) == TradingEvent.ShortOpen && (unit.AsksCount/ unit.BidsCount>2 ))
|
||||
// {
|
||||
// declisionsForSave.Add(new Declision()
|
||||
// {
|
||||
// AccountId = string.Empty,
|
||||
// Figi = message.Figi,
|
||||
// Ticker = message.Ticker,
|
||||
// Price = message.Value,
|
||||
// Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
// Action = DeclisionTradeAction.OpenShort,
|
||||
// });
|
||||
// }
|
||||
if ((result & TradingEvent.LongOpen) == TradingEvent.LongOpen
|
||||
&& ((unit.BidsCount / unit.AsksCount) > 0.5m))
|
||||
{
|
||||
if (BuyStops.TryGetValue(message.Figi, out var dt))
|
||||
{
|
||||
if (dt > (message.IsHistoricalData ? message.Time : DateTime.UtcNow))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
BuyStops.TryRemove(message.Figi, out _);
|
||||
}
|
||||
}
|
||||
|
||||
// using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
// context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
declisionsForSave.Add(new Declision()
|
||||
{
|
||||
AccountId = string.Empty,
|
||||
Figi = message.Figi,
|
||||
Ticker = message.Ticker,
|
||||
Price = message.Value,
|
||||
Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
Action = DeclisionTradeAction.OpenLong,
|
||||
});
|
||||
}
|
||||
|
||||
// await context.AddRangeAsync(declisionsForSave);
|
||||
// await context.SaveChangesAsync();
|
||||
// }
|
||||
//}
|
||||
if ((result & TradingEvent.LongClose) == TradingEvent.LongClose)
|
||||
{
|
||||
declisionsForSave.Add(new Declision()
|
||||
{
|
||||
AccountId = string.Empty,
|
||||
Figi = message.Figi,
|
||||
Ticker = message.Ticker,
|
||||
Price = message.Value,
|
||||
Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
Action = DeclisionTradeAction.CloseLong,
|
||||
});
|
||||
}
|
||||
|
||||
if ((result & TradingEvent.ShortOpen) == TradingEvent.ShortOpen && (unit.BidsCount / unit.AsksCount < 2))
|
||||
{
|
||||
declisionsForSave.Add(new Declision()
|
||||
{
|
||||
AccountId = string.Empty,
|
||||
Figi = message.Figi,
|
||||
Ticker = message.Ticker,
|
||||
Price = message.Value,
|
||||
Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
Action = DeclisionTradeAction.OpenShort,
|
||||
});
|
||||
}
|
||||
|
||||
if ((result & TradingEvent.ShortClose) == TradingEvent.ShortClose)
|
||||
{
|
||||
declisionsForSave.Add(new Declision()
|
||||
{
|
||||
AccountId = string.Empty,
|
||||
Figi = message.Figi,
|
||||
Ticker = message.Ticker,
|
||||
Price = message.Value,
|
||||
Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||
Action = DeclisionTradeAction.CloseShort,
|
||||
});
|
||||
}
|
||||
|
||||
if (declisionsForSave.Count > 0)
|
||||
{
|
||||
using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
|
||||
await context.AddRangeAsync(declisionsForSave);
|
||||
await context.SaveChangesAsync();
|
||||
declisionsForSave.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,27 +255,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
}
|
||||
|
||||
private async Task BackgroundWorker()
|
||||
{
|
||||
var keysForRemove = new List<string>();
|
||||
while (!_cts.IsCancellationRequested)
|
||||
{
|
||||
var time = DateTime.UtcNow;
|
||||
foreach (var kvp in BuyStops)
|
||||
{
|
||||
if (kvp.Value > time)
|
||||
{
|
||||
keysForRemove.Add(kvp.Key);
|
||||
}
|
||||
}
|
||||
foreach (var key in keysForRemove)
|
||||
{
|
||||
BuyStops.TryRemove(key, out _);
|
||||
}
|
||||
await Task.Delay(10000);
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_cts.Cancel();
|
||||
|
|
Loading…
Reference in New Issue