реализация нового критерия выставления точки на базе дивергенции
parent
03b0f5582e
commit
50938f093e
|
@ -188,10 +188,10 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
|
||||
if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2])
|
||||
{
|
||||
if (!uptrendEndingDetectionMeanfullStep.HasValue || ((d1 >= uptrendEndingDetectionMeanfullStep
|
||||
if (!uptrendEndingDetectionMeanfullStep.HasValue || ((d1 >= uptrendEndingDetectionMeanfullStep
|
||||
//|| d2 >= uptrendEndingDetectionMeanfullStep
|
||||
)
|
||||
&& dt>TimeSpan.FromSeconds(10)))
|
||||
)
|
||||
&& dt > TimeSpan.FromSeconds(10)))
|
||||
{
|
||||
res |= TradingEvent.UptrendEnd;
|
||||
}
|
||||
|
@ -200,8 +200,8 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
// если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта
|
||||
if (twavss[size - 1] >= twavbs[size - 1] && twavss[size - 2] < twavbs[size - 2])
|
||||
{
|
||||
if (!uptrendStartingDetectionMeanfullStep.HasValue ||( (d1 <= uptrendStartingDetectionMeanfullStep
|
||||
// || d2 <= uptrendStartingDetectionMeanfullStep
|
||||
if (!uptrendStartingDetectionMeanfullStep.HasValue || ((d1 <= uptrendStartingDetectionMeanfullStep
|
||||
// || d2 <= uptrendStartingDetectionMeanfullStep
|
||||
) && dt > TimeSpan.FromSeconds(10)))
|
||||
{
|
||||
res |= TradingEvent.UptrendStart;
|
||||
|
|
|
@ -59,10 +59,10 @@
|
|||
{
|
||||
if (values.Length < 1) throw new ArgumentException();
|
||||
|
||||
var resArray = new decimal[values.Length-1];
|
||||
for (int i=1; i<values.Length; i++)
|
||||
var resArray = new decimal[values.Length - 1];
|
||||
for (int i = 1; i < values.Length; i++)
|
||||
{
|
||||
resArray[i - 1] = values[i] - values[i-1];
|
||||
resArray[i - 1] = values[i] - values[i - 1];
|
||||
}
|
||||
return resArray;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
using KLHZ.Trader.Core.Contracts.Declisions.Dtos;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||||
{
|
||||
|
@ -12,13 +7,14 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
|
||||
public static decimal Mean(this CachedValue[] values)
|
||||
{
|
||||
return values.Sum(x => x.Value)/ values.Length;
|
||||
return values.Sum(x => x.Value) / values.Length;
|
||||
}
|
||||
|
||||
public static decimal Mean2(this CachedValue[] values)
|
||||
{
|
||||
return values.Sum(x => x.Value2) / values.Length;
|
||||
}
|
||||
|
||||
private static (decimal mean, decimal std) CaclSigma(decimal[] values)
|
||||
{
|
||||
var mean = values.Sum() / values.Length;
|
||||
|
@ -30,12 +26,12 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
data[i] = v * v;
|
||||
}
|
||||
var std = System.Math.Pow((double)(data.Sum() / (data.Length - 1)), 0.5);
|
||||
return (mean,(decimal)std);
|
||||
return (mean, (decimal)std);
|
||||
}
|
||||
|
||||
public static decimal[] ClearNSigmaReqursive(decimal[] values, int depth = 0, int sigmasCount = 3)
|
||||
{
|
||||
if (values.Length <= 1 || depth>10) return values;
|
||||
if (values.Length <= 1 || depth > 10) return values;
|
||||
var sigmaRes = CaclSigma(values);
|
||||
var std = sigmaRes.std;
|
||||
var mean = sigmaRes.mean;
|
||||
|
@ -43,19 +39,72 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
var _3std = sigmasCount * std;
|
||||
foreach (var v in values)
|
||||
{
|
||||
if (System.Math.Abs(mean - v)< _3std)
|
||||
if (System.Math.Abs(mean - v) < _3std)
|
||||
{
|
||||
forRes.Add(v);
|
||||
}
|
||||
}
|
||||
if (forRes.Count != values.Length)
|
||||
{
|
||||
return ClearNSigmaReqursive(forRes.ToArray(), depth+1);
|
||||
return ClearNSigmaReqursive(forRes.ToArray(), depth + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return forRes.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryCalcTimeWindowsDiff(this CachedValue[] values, TimeSpan boundLeft, TimeSpan boundRight,
|
||||
Func<CachedValue, decimal> fieldSelector, bool calcMean, out decimal result)
|
||||
{
|
||||
result = default;
|
||||
if (values.Length > 1)
|
||||
{
|
||||
var shiftTimeR = values.Last().Time - boundRight;
|
||||
var shiftTimeL = values.Last().Time - boundLeft;
|
||||
|
||||
var valuesOld = values.Where(b => b.Time < shiftTimeR && b.Time >= shiftTimeL).ToArray();
|
||||
var valuesNew = values.Where(b => b.Time >= shiftTimeR).ToArray();
|
||||
|
||||
if (valuesOld.Length > 0 && valuesNew.Length > 0)
|
||||
{
|
||||
var valNew = valuesNew.Sum(fieldSelector);
|
||||
var valOld = valuesOld.Sum(fieldSelector);
|
||||
|
||||
if (calcMean)
|
||||
{
|
||||
valNew = valNew / valuesNew.Length;
|
||||
valOld = valOld / valuesOld.Length;
|
||||
}
|
||||
result = valNew - valOld;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryCalcPirsonCorrelation(this CachedValue[] values, TimeSpan period, out decimal result)
|
||||
{
|
||||
result = default;
|
||||
if (values.Any())
|
||||
{
|
||||
var shiftTimeDiffs1 = values.Last().Time - period;
|
||||
values = values.Where(b => b.Time >= shiftTimeDiffs1).ToArray();
|
||||
if (values.Any())
|
||||
{
|
||||
var tradevolume_diffMean = values.Mean();
|
||||
var dprice_diffMean = values.Mean2();
|
||||
var sum1 = (double)values.Sum(d => (d.Value - tradevolume_diffMean) * (d.Value2 - dprice_diffMean));
|
||||
var sum2 = values.Sum(d => (d.Value - tradevolume_diffMean) * (d.Value - tradevolume_diffMean));
|
||||
var sum3 = values.Sum(d => (d.Value2 - dprice_diffMean) * (d.Value2 - dprice_diffMean));
|
||||
if (sum2 != 0 && sum3 != 0)
|
||||
{
|
||||
result = (decimal)(sum1 / System.Math.Sqrt((double)(sum2 * sum3)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
var res = SignalProcessing.CalcDiffs(da.ToArray());
|
||||
|
||||
Assert.IsTrue(res.Length - da.Count == -1);
|
||||
foreach(var r in res)
|
||||
foreach (var r in res)
|
||||
{
|
||||
Assert.IsTrue(r == 1);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
using KLHZ.Trader.Core.Math.Declisions.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace KLHZ.Trader.Core.Tests
|
||||
{
|
||||
|
@ -14,7 +9,7 @@ namespace KLHZ.Trader.Core.Tests
|
|||
public static void Test()
|
||||
{
|
||||
var data = new decimal[1000];
|
||||
for(int i = 0; i < data.Length; i++)
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] = RandomNumberGenerator.GetInt32(-10, 10);
|
||||
}
|
||||
|
|
|
@ -40,8 +40,16 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
private readonly ConcurrentDictionary<string, TradingMode> TradingModes = new();
|
||||
private readonly ConcurrentDictionary<string, IOrderbook> OrderBooks = new();
|
||||
|
||||
private readonly ConcurrentDictionary<string, (DateTime, decimal)> volumes = new();
|
||||
private readonly ConcurrentDictionary<string, (DateTime, decimal)> prices = new();
|
||||
private readonly ConcurrentDictionary<string, decimal> privces = new();
|
||||
private readonly ConcurrentDictionary<string, decimal> privcesDiffDiff = new();
|
||||
private readonly ConcurrentDictionary<string, decimal> privcesDiffDiffPrev = new();
|
||||
private readonly ConcurrentDictionary<string, decimal> correlations = new();
|
||||
private readonly ConcurrentDictionary<string, decimal> correlationsPrev = new();
|
||||
private readonly ConcurrentDictionary<string, DateTime> PirsonZeroCrossings = new();
|
||||
private readonly ConcurrentDictionary<string, decimal> DPirsonValues = new();
|
||||
|
||||
private readonly ConcurrentDictionary<string, DateTime> PricesZeroCrossingsUp = new();
|
||||
private readonly ConcurrentDictionary<string, DateTime> PricesZeroCrossingsDown = new();
|
||||
|
||||
private readonly ConcurrentDictionary<string, DateTime> LongOpeningStops = new();
|
||||
private readonly ConcurrentDictionary<string, DateTime> ShortOpeningStops = new();
|
||||
|
@ -50,7 +58,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
private readonly ConcurrentDictionary<string, InstrumentSettings> Leverages = new();
|
||||
|
||||
|
||||
|
||||
private readonly decimal _futureComission;
|
||||
private readonly decimal _shareComission;
|
||||
private readonly decimal _accountCashPart;
|
||||
|
@ -283,7 +290,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
// if (val != 0)
|
||||
// await LogPrice(message.Figi, message.Ticker, message.Time, val, "asks0");
|
||||
// }
|
||||
|
||||
|
||||
//}
|
||||
OrderBooks[message.Figi] = message;
|
||||
}
|
||||
|
@ -297,6 +304,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
while (await _pricesChannel.Reader.WaitToReadAsync())
|
||||
{
|
||||
var message = await _pricesChannel.Reader.ReadAsync();
|
||||
if (!message.IsHistoricalData && DateTime.UtcNow - message.Time > TimeSpan.FromMinutes(1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var changeMods = GetInitDict(0);
|
||||
try
|
||||
{
|
||||
|
@ -368,7 +379,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
|
||||
#region Подсчёт торгового баланса по сберу и IMOEXF
|
||||
if (message.Figi == "BBG004730N88" || message.Figi == "FUTIMOEXF000")
|
||||
{
|
||||
{
|
||||
if (message.Direction == 1)
|
||||
{
|
||||
|
||||
|
@ -428,103 +439,134 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//var buys = await _tradeDataProvider.GetDataFrom20SecondsWindowCache(message.Figi, "1");
|
||||
//var sells = await _tradeDataProvider.GetDataFrom20SecondsWindowCache(message.Figi, "2");
|
||||
|
||||
|
||||
//var buysSpeed = buys.Sum(p => p.Value) / 20;
|
||||
//var sellsSpeed = sells.Sum(p => p.Value) / 20;
|
||||
|
||||
//var orderBook = _tradeDataProvider.Orderbooks[message.Figi];
|
||||
//if (orderBook.Asks.Length>3 && orderBook.Bids.Length>3)
|
||||
//{
|
||||
// var asks = (decimal)(orderBook.Asks[0].Count + orderBook.Asks[1].Count + orderBook.Asks[2].Count);
|
||||
// //var asks = (decimal)(orderBook.Asks[0].Count + orderBook.Asks[1].Count + orderBook.Asks[2].Count + orderBook.Asks[3].Count);
|
||||
// var bids = (decimal)(orderBook.Bids[0].Count + orderBook.Bids[1].Count + orderBook.Bids[2].Count);
|
||||
// //var bids = (decimal)(orderBook.Bids[0].Count + orderBook.Bids[1].Count + orderBook.Bids[2].Count + orderBook.Bids[3].Count);
|
||||
|
||||
// if (buysSpeed > 0 && sellsSpeed > 0)
|
||||
// {
|
||||
// await LogPrice(message, "speed_relation", (sellsSpeed / (sellsSpeed + buysSpeed)));
|
||||
// }
|
||||
|
||||
// //var diff = buysSpeed - sellsSpeed;
|
||||
// //await LogPrice(message, "speed_diff", diff);
|
||||
// //await LogPrice(message, "stabling", (asks+bids)/(sellsSpeed+buysSpeed));
|
||||
|
||||
// if (buysSpeed > 0)
|
||||
// {
|
||||
// var asksLifetime = asks / buysSpeed;
|
||||
// if (asksLifetime > 600) asksLifetime = 600;
|
||||
// await LogPrice(message, "asks_lifetime", asksLifetime);
|
||||
// await LogPrice(message, "buys_speed", buysSpeed);
|
||||
// }
|
||||
|
||||
|
||||
// if (sellsSpeed > 0)
|
||||
// {
|
||||
// var bidsLifetime = bids / sellsSpeed;
|
||||
// if (bidsLifetime > 600) bidsLifetime = 600;
|
||||
// await LogPrice(message, "bids_lifetime", bidsLifetime);
|
||||
// await LogPrice(message, "sells_speed", sellsSpeed);
|
||||
// }
|
||||
|
||||
|
||||
// //var buys5min = await _tradeDataProvider.GetDataFrom5MinuteWindowCache(message.Figi, Constants._5minBuyCacheKey);
|
||||
// //var sells5min = await _tradeDataProvider.GetDataFrom5MinuteWindowCache(message.Figi, Constants._5minSellCacheKey);
|
||||
// //var buysSpeed5min = buys5min.Sum(p => p.Value) / 300;
|
||||
// //var sellsSpeed5min = sells5min.Sum(p => p.Value) / 300;
|
||||
// //var diff5min = buysSpeed5min - sellsSpeed5min;
|
||||
// //await LogPrice(message, "speed_diff_5min", diff5min);
|
||||
|
||||
// //var buys1min = await _tradeDataProvider.GetDataFrom1MinuteWindowCache(message.Figi, Constants._1minBuyCacheKey);
|
||||
// //var sells1min = await _tradeDataProvider.GetDataFrom1MinuteWindowCache(message.Figi, Constants._1minSellCacheKey);
|
||||
// //var buysSpeed1min = buys1min.Sum(p => p.Value) / 60;
|
||||
// //var sellsSpeed1min = sells1min.Sum(p => p.Value) / 60;
|
||||
// //var diff1min = buysSpeed1min - sellsSpeed1min;
|
||||
// //await LogPrice(message, "speed_diff_1min", diff1min);
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
if (_tradingInstrumentsFigis.Contains(message.Figi) && message.Figi == "FUTIMOEXF000" && message.Direction == 1)
|
||||
if (_tradingInstrumentsFigis.Contains(message.Figi) && (message.Figi == "FUTIMOEXF000" || message.Figi == "BBG004730N88") && message.Direction == 1)
|
||||
{
|
||||
var smallWindow = TimeSpan.FromSeconds(120);
|
||||
var bigWindow = TimeSpan.FromSeconds(240);
|
||||
var meanWindow = TimeSpan.FromSeconds(240);
|
||||
var currentTime = message.IsHistoricalData ? message.Time : DateTime.UtcNow;
|
||||
try
|
||||
{
|
||||
var buys = await _tradeDataProvider.GetDataFrom5MinuteWindowCache(message.Figi, Constants._5minBuyCacheKey);
|
||||
var sells = await _tradeDataProvider.GetDataFrom5MinuteWindowCache(message.Figi, Constants._5minSellCacheKey);
|
||||
if (buys.Any() && sells.Any())
|
||||
var buys = await _tradeDataProvider.GetDataFrom15MinuteWindowCache(message.Figi, Constants._15minBuyCacheKey);
|
||||
var sells = await _tradeDataProvider.GetDataFrom15MinuteWindowCache(message.Figi, Constants._15minSellCacheKey);
|
||||
var trades = buys.ToList();
|
||||
trades.AddRange(sells);
|
||||
var trades2 = trades.OrderBy(t => t.Time).ToArray();
|
||||
if (trades2.TryCalcTimeWindowsDiff(bigWindow, smallWindow, v => v.Value, false, out var tradesDiff)
|
||||
&& buys.TryCalcTimeWindowsDiff(bigWindow, smallWindow, v => v.Value2, true, out var pricesDiff))
|
||||
{
|
||||
var shiftTimeB2 = buys.Last().Time - TimeSpan.FromSeconds(150);
|
||||
var shiftTimeS2 = sells.Last().Time - TimeSpan.FromSeconds(150);
|
||||
var shiftTimeB1 = buys.Last().Time - TimeSpan.FromSeconds(300);
|
||||
var shiftTimeS1 = sells.Last().Time - TimeSpan.FromSeconds(300);
|
||||
var buysOld = buys.Where(b => b.Time < shiftTimeB2 && b.Time >= shiftTimeB1).ToArray();
|
||||
var sellsOld = sells.Where(b => b.Time < shiftTimeS2 && b.Time >= shiftTimeS1).ToArray();
|
||||
|
||||
var buysNew = buys.Where(b => b.Time >= shiftTimeB2).ToArray();
|
||||
var sellsNew = sells.Where(b => b.Time >= shiftTimeS2).ToArray();
|
||||
|
||||
|
||||
if (buysOld.Any() && sellsOld.Any() && sellsNew.Any() && buysNew.Any())
|
||||
await LogPrice(message, "privcesDiff", pricesDiff);
|
||||
await LogPrice(message, "tradevolume_diff", tradesDiff);
|
||||
await _tradeDataProvider.AddDataTo15MinuteWindowCache(message.Figi, "5min_diff", new Contracts.Declisions.Dtos.CachedValue()
|
||||
{
|
||||
var volume = buysNew.Sum(b => b.Value) + sellsNew.Sum(b => b.Value);
|
||||
var volumeOld = buysOld.Sum(b => b.Value) + sellsOld.Sum(b => b.Value);
|
||||
var price = buysNew.Mean2();
|
||||
var priceOld = buysOld.Mean2();
|
||||
Time = message.Time,
|
||||
Value = tradesDiff,
|
||||
Value2 = pricesDiff,
|
||||
});
|
||||
|
||||
await LogPrice(message, "tradevolume", volume);
|
||||
await LogPrice(message, "privcesDiff", price- priceOld);
|
||||
await LogPrice(message, "tradevolume_diff", volume - volumeOld);
|
||||
var diffs = await _tradeDataProvider.GetDataFrom15MinuteWindowCache(message.Figi, "5min_diff");
|
||||
if (diffs.TryCalcTimeWindowsDiff(bigWindow, smallWindow, (c) => c.Value2, true, out var resdp)
|
||||
&& diffs.TryCalcTimeWindowsDiff(bigWindow, smallWindow, (c) => c.Value, true, out var resv))
|
||||
{
|
||||
await LogPrice(message, "privcesDiffDiff", (decimal)resdp);
|
||||
await LogPrice(message, "tradevolume_diff_diff", (decimal)resv);
|
||||
await _tradeDataProvider.AddDataTo15MinuteWindowCache(message.Figi, "5min_diff_diff", new Contracts.Declisions.Dtos.CachedValue()
|
||||
{
|
||||
Time = message.Time,
|
||||
Value = resv,
|
||||
Value2 = resdp,
|
||||
});
|
||||
if (diffs.TryCalcPirsonCorrelation(meanWindow, out var pirson))
|
||||
{
|
||||
await LogPrice(message, "diffs_pirson", (decimal)pirson);
|
||||
await _tradeDataProvider.AddDataTo15MinuteWindowCache(message.Figi, "diffs_pirson", new Contracts.Declisions.Dtos.CachedValue()
|
||||
{
|
||||
Time = message.Time,
|
||||
Value = (decimal)pirson,
|
||||
});
|
||||
if (pirson < 0)
|
||||
{
|
||||
//PirsonZeroCrossings["FUTIMOEXF000"] = message.Time;
|
||||
PirsonZeroCrossings[message.Figi] = message.Time;
|
||||
// await SetEvents(message);
|
||||
}
|
||||
var diffs_pirson = await _tradeDataProvider.GetDataFrom15MinuteWindowCache(message.Figi, "diffs_pirson");
|
||||
if (diffs_pirson.TryCalcTimeWindowsDiff(bigWindow, smallWindow, (c) => c.Value, true, out var res))
|
||||
{
|
||||
await LogPrice(message, "diffs_pirson_diff", (decimal)res);
|
||||
if (DPirsonValues.TryGetValue(message.Figi, out var olddpirs))
|
||||
{
|
||||
if (olddpirs < 0 && res > 0)
|
||||
{
|
||||
await LogPrice(message, "diffs_pirson_diff_point0", message.Value);
|
||||
}
|
||||
if (olddpirs < 0.25m && res > 0.25m)
|
||||
{
|
||||
await LogPrice(message, "diffs_pirson_diff_point0.25", message.Value);
|
||||
}
|
||||
if (olddpirs < 0.5m && res > 0.5m)
|
||||
{
|
||||
await LogPrice(message, "diffs_pirson_diff_point0.5", message.Value);
|
||||
}
|
||||
}
|
||||
DPirsonValues[message.Figi] = res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var diffdiff = await _tradeDataProvider.GetDataFrom15MinuteWindowCache(message.Figi, "5min_diff_diff");
|
||||
|
||||
|
||||
//resdp = diffdiff.Where(d => message.Time - d.Time < TimeSpan.FromSeconds(45)).ToArray().Mean2();
|
||||
|
||||
if (privcesDiffDiff.TryGetValue(message.Figi, out var priceOld))
|
||||
{
|
||||
privcesDiffDiffPrev[message.Figi] = priceOld;
|
||||
}
|
||||
privcesDiffDiff[message.Figi] = pricesDiff;
|
||||
|
||||
if (privcesDiffDiff.TryGetValue(message.Figi, out var dprice2)
|
||||
&& privcesDiffDiffPrev.TryGetValue(message.Figi, out var dprice2_prev))
|
||||
{
|
||||
if (((dprice2 < 0 && dprice2_prev > 0) || (dprice2 > 0 && dprice2_prev < 0)))
|
||||
{
|
||||
if (PirsonZeroCrossings.TryGetValue(message.Figi, out var pir)
|
||||
&& message.Time - pir < TimeSpan.FromSeconds(60))
|
||||
{
|
||||
if (pricesDiff < 0)
|
||||
{
|
||||
PricesZeroCrossingsDown["FUTIMOEXF000"] = message.Time;
|
||||
//await SetEvents(message);
|
||||
await LogPrice(message, "price_diff2_point_short", message.Value);
|
||||
}
|
||||
if (pricesDiff > 0)
|
||||
{
|
||||
PricesZeroCrossingsUp["FUTIMOEXF000"] = message.Time;
|
||||
//await SetEvents(message);
|
||||
await LogPrice(message, "price_diff2_point_long", message.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (diffdiff.TryCalcPirsonCorrelation(meanWindow, out var pirson2))
|
||||
{
|
||||
if (correlations.TryGetValue(message.Figi, out var corr))
|
||||
{
|
||||
correlationsPrev[message.Figi] = corr;
|
||||
}
|
||||
await LogPrice(message, "diffs2_pirson", (decimal)pirson2);
|
||||
correlations[message.Figi] = pirson2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (timesCache.TryGetValue(message.Figi, out var dt))
|
||||
{
|
||||
if ((message.Time - dt).TotalSeconds > 10)
|
||||
|
@ -600,11 +642,11 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
{
|
||||
if (message.Direction != 1) continue;
|
||||
await _tradeDataProvider.AddData(message);
|
||||
ProcessStops(message, currentTime);
|
||||
//ProcessStops(message, currentTime);
|
||||
var windowMaxSize = 2000;
|
||||
var data = await _tradeDataProvider.GetData(message.Figi, windowMaxSize);
|
||||
var state = ExchangeScheduler.GetCurrentState(message.Time);
|
||||
await ProcessNewPriceIMOEXF3(data, state, message, windowMaxSize, changeMods.ToImmutableDictionary());
|
||||
//var data = await _tradeDataProvider.GetData(message.Figi, windowMaxSize);
|
||||
//var state = ExchangeScheduler.GetCurrentState(message.Time);
|
||||
// await ProcessNewPriceIMOEXF3(data, state, message, windowMaxSize, changeMods.ToImmutableDictionary());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -620,6 +662,28 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
private async Task SetEvents(INewPrice message)
|
||||
{
|
||||
DateTime pz = DateTime.MinValue;
|
||||
if (PirsonZeroCrossings.TryGetValue(message.Figi, out var pir))
|
||||
{
|
||||
if (PricesZeroCrossingsDown.TryGetValue(message.Figi, out pz))
|
||||
{
|
||||
if (message.Time - pir < TimeSpan.FromSeconds(120) && message.Time - pz < TimeSpan.FromSeconds(120))
|
||||
{
|
||||
await LogPrice(message, "price_diff2_point_short", message.Value);
|
||||
}
|
||||
}
|
||||
if (PricesZeroCrossingsUp.TryGetValue(message.Figi, out pz))
|
||||
{
|
||||
if (message.Time - pir < TimeSpan.FromSeconds(120) && message.Time - pz < TimeSpan.FromSeconds(120))
|
||||
{
|
||||
await LogPrice(message, "price_diff2_point_long", message.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private async Task<ImmutableDictionary<TradingEvent, decimal>> CheckDivergency(DateTime[] timestamps, decimal[] values, INewPrice message)
|
||||
{
|
||||
var res = GetInitDict(1);
|
||||
|
@ -665,19 +729,19 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
});
|
||||
await LogPrice(message, "speed_diff_15min", diff5min);
|
||||
|
||||
|
||||
|
||||
var orderBook = _tradeDataProvider.Orderbooks[message.Figi];
|
||||
if (orderBook.Asks.Length > 3 && orderBook.Bids.Length > 3)
|
||||
{
|
||||
var asks = (decimal)(orderBook.Asks[0].Count + orderBook.Asks[1].Count/2 + orderBook.Asks[2].Count/4);
|
||||
var asks = (decimal)(orderBook.Asks[0].Count + orderBook.Asks[1].Count / 2 + orderBook.Asks[2].Count / 4);
|
||||
//var asks = (decimal)(orderBook.Asks[0].Count + orderBook.Asks[1].Count + orderBook.Asks[2].Count + orderBook.Asks[3].Count);
|
||||
var bids = (decimal)(orderBook.Bids[0].Count + orderBook.Bids[1].Count/2 + orderBook.Bids[2].Count/4);
|
||||
var bids = (decimal)(orderBook.Bids[0].Count + orderBook.Bids[1].Count / 2 + orderBook.Bids[2].Count / 4);
|
||||
var asks_lifetime = asks / buysSpeed5min;
|
||||
var bids_lifetime = bids / sellsSpeed5min;
|
||||
var changeModIndicator = (asks_lifetime - bids_lifetime) / (asks_lifetime + bids_lifetime);
|
||||
await LogPrice(message, "asks_lifetime", asks_lifetime);
|
||||
await LogPrice(message, "bids_lifetime", bids_lifetime);
|
||||
|
||||
|
||||
|
||||
await _tradeDataProvider.AddDataTo20SecondsWindowCache(message.Figi, "changemode", new Contracts.Declisions.Dtos.CachedValue()
|
||||
{
|
||||
|
@ -748,13 +812,13 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
decimal? diff2 = null;
|
||||
if (cached.Length > 1)
|
||||
{
|
||||
if (cached[cached.Length-1].Time - cached[0].Time > TimeSpan.FromMinutes(3.5))
|
||||
if (cached[cached.Length - 1].Time - cached[0].Time > TimeSpan.FromMinutes(3.5))
|
||||
{
|
||||
diff2 = cached[cached.Length - 1].Value - cached[0].Value;
|
||||
await LogPrice(message, "changemode2", diff2.Value);
|
||||
}
|
||||
}
|
||||
if (diff5min < -0.2m || (diff2.HasValue && diff2<-0.3m))
|
||||
if (diff5min < -0.2m || (diff2.HasValue && diff2 < -0.3m))
|
||||
{
|
||||
res[TradingEvent.UptrendStart] = Constants.BlockingCoefficient;
|
||||
}
|
||||
|
@ -789,17 +853,90 @@ INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullS
|
|||
res[TradingEvent.UptrendEnd] = Constants.PowerLowingCoefficient;
|
||||
if ((resultMoveAvFull.events & TradingEvent.UptrendStart) == TradingEvent.UptrendStart)
|
||||
{
|
||||
res[TradingEvent.UptrendStart] = Constants.PowerUppingCoefficient;
|
||||
res[TradingEvent.DowntrendEnd] = Constants.PowerUppingCoefficient;
|
||||
res[TradingEvent.UptrendStart] = Constants.UppingCoefficient;
|
||||
//res[TradingEvent.DowntrendEnd] = Constants.UppingCoefficient;
|
||||
}
|
||||
if ((resultMoveAvFull.events & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
|
||||
{
|
||||
res[TradingEvent.UptrendEnd] = Constants.PowerUppingCoefficient;
|
||||
res[TradingEvent.DowntrendStart] = Constants.PowerUppingCoefficient;
|
||||
//res[TradingEvent.UptrendEnd] = Constants.UppingCoefficient;
|
||||
res[TradingEvent.DowntrendStart] = Constants.UppingCoefficient;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private async Task<Dictionary<TradingEvent, decimal>> GetPriceDiff2Mods((DateTime[] timestamps, decimal[] prices) data, int smallWindow, int bigWindow,
|
||||
INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullStep = null, decimal? uptrendEndingDetectionMeanfullStep = null)
|
||||
{
|
||||
var res = GetInitDict(0);
|
||||
|
||||
if (privcesDiffDiff.TryGetValue(message.Figi, out var dprice2) && privcesDiffDiffPrev.TryGetValue(message.Figi, out var dprice2_prev))
|
||||
{
|
||||
if ((dprice2 < 0 && dprice2_prev > 0) || (dprice2 > 0 && dprice2_prev < 0))
|
||||
{
|
||||
res[TradingEvent.DowntrendStart] = Constants.UppingCoefficient;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
//res[TradingEvent.DowntrendEnd] = Constants.PowerLowingCoefficient;
|
||||
//res[TradingEvent.UptrendEnd] = Constants.PowerLowingCoefficient;
|
||||
//if ((resultMoveAvFull.events & TradingEvent.UptrendStart) == TradingEvent.UptrendStart)
|
||||
//{
|
||||
// res[TradingEvent.UptrendStart] = Constants.UppingCoefficient;
|
||||
// //res[TradingEvent.DowntrendEnd] = Constants.UppingCoefficient;
|
||||
//}
|
||||
//if ((resultMoveAvFull.events & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
|
||||
//{
|
||||
// //res[TradingEvent.UptrendEnd] = Constants.UppingCoefficient;
|
||||
// res[TradingEvent.DowntrendStart] = Constants.UppingCoefficient;
|
||||
//}
|
||||
//return res;
|
||||
}
|
||||
|
||||
|
||||
private async Task<Dictionary<TradingEvent, decimal>> GetWindowAverageStartData2((DateTime[] timestamps, decimal[] prices) data, int smallWindow, int bigWindow,
|
||||
INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullStep = null, decimal? uptrendEndingDetectionMeanfullStep = null)
|
||||
{
|
||||
var res = GetInitDict(0);
|
||||
var resultMoveAvFull = MovingAverage.CheckByWindowAverageMean2(data.timestamps, data.prices,
|
||||
windowMaxSize, smallWindow, bigWindow, uptrendStartingDetectionMeanfullStep, uptrendEndingDetectionMeanfullStep);
|
||||
if (resultMoveAvFull.bigWindowAv != 0)
|
||||
{
|
||||
await LogPrice(message, Constants.BigWindowCrossingAverageProcessor, resultMoveAvFull.bigWindowAv);
|
||||
await LogPrice(message, Constants.SmallWindowCrossingAverageProcessor, resultMoveAvFull.smallWindowAv);
|
||||
}
|
||||
|
||||
if (correlationsPrev.TryGetValue(message.Figi, out var oldC) && correlations.TryGetValue(message.Figi, out var c))
|
||||
{
|
||||
if ((oldC < 0 && c > 0) || (oldC > 0 && c < 0))
|
||||
{
|
||||
if (resultMoveAvFull.bigWindowAv - resultMoveAvFull.smallWindowAv > 0.5m)
|
||||
{
|
||||
res[TradingEvent.DowntrendStart] = Constants.UppingCoefficient;
|
||||
}
|
||||
|
||||
if (resultMoveAvFull.smallWindowAv - resultMoveAvFull.bigWindowAv > 0.5m)
|
||||
{
|
||||
res[TradingEvent.UptrendStart] = Constants.UppingCoefficient;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return res;
|
||||
//res[TradingEvent.DowntrendEnd] = Constants.PowerLowingCoefficient;
|
||||
//res[TradingEvent.UptrendEnd] = Constants.PowerLowingCoefficient;
|
||||
//if ((resultMoveAvFull.events & TradingEvent.UptrendStart) == TradingEvent.UptrendStart)
|
||||
//{
|
||||
// res[TradingEvent.UptrendStart] = Constants.UppingCoefficient;
|
||||
// //res[TradingEvent.DowntrendEnd] = Constants.UppingCoefficient;
|
||||
//}
|
||||
//if ((resultMoveAvFull.events & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
|
||||
//{
|
||||
// //res[TradingEvent.UptrendEnd] = Constants.UppingCoefficient;
|
||||
// res[TradingEvent.DowntrendStart] = Constants.UppingCoefficient;
|
||||
//}
|
||||
//return res;
|
||||
}
|
||||
|
||||
private async Task<decimal?> GetAreasRelation((DateTime[] timestamps, decimal[] prices) data, INewPrice message)
|
||||
{
|
||||
var areasRel = -1m;
|
||||
|
@ -927,7 +1064,9 @@ INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullS
|
|||
var steps = await GetSteps(message);
|
||||
var windows = await GetWindowsSizes(message);
|
||||
//var resTask1 = GetWindowAverageStartData(data, 30, 180, message, windowMaxSize, -2m, 2m,3);
|
||||
var resTask1 = GetWindowAverageStartData(data, (int)windows.smallWindow, (int)windows.bigWindow, message, windowMaxSize, steps.downtrendEndStep, steps.uptrendEndStep);
|
||||
var resTask1 = GetWindowAverageStartData2(data, (int)windows.smallWindow, (int)windows.bigWindow, message, windowMaxSize, steps.downtrendEndStep, steps.uptrendEndStep);
|
||||
|
||||
var corrModsTask = GetCorrelationsMods(message);
|
||||
////var resTask3 = GetWindowAverageStartData(data, 30, 180, message, windowMaxSize, 0, 0,0.7m);
|
||||
//var getFFTModsTask = GetFFTMods(message);
|
||||
//var getLocalTrendsModsTask = GetLocalTrendsMods(data, message);
|
||||
|
@ -946,13 +1085,16 @@ INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullS
|
|||
|
||||
//result = MergeResults(result, resTask2.Result.ToImmutableDictionary());
|
||||
//result = MergeResults(result, resTask3.Result.ToImmutableDictionary());
|
||||
result = MergeResultsMax(result, changeModeData);
|
||||
//result = MergeResultsMax(result, changeModeData);
|
||||
//result = MergeResultsMult(result, corrModsTask.Result);
|
||||
// result = MergeResultsMax(result, getLocalTrendsModsTask.Result);
|
||||
//result = MergeResultsMult(result, getFFTModsTask.Result);
|
||||
//result = MergeResultsMult(result, getSellsDiffsModsTask.Result);
|
||||
//result = MergeResultsMult(result, getTradingModeModsTask.Result);
|
||||
//result = MergeResultsMult(result, getSpeedResultantModsTask.Result);
|
||||
|
||||
|
||||
|
||||
if (result[TradingEvent.UptrendStart] >= Constants.UppingCoefficient
|
||||
&& !LongOpeningStops.ContainsKey(message.Figi)
|
||||
&& state == ExchangeState.Open
|
||||
|
@ -996,7 +1138,7 @@ INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullS
|
|||
await LogDeclision(DeclisionTradeAction.ResetStopsShort, message.Value - stops.takeProfit, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message);
|
||||
await LogDeclision(DeclisionTradeAction.ResetStopsShort, message.Value + stops.stopLoss, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message);
|
||||
}
|
||||
if (result[TradingEvent.UptrendEnd] >= Constants.UppingCoefficient)
|
||||
if (result[TradingEvent.UptrendEnd] >= Constants.UppingCoefficient * 10)
|
||||
{
|
||||
if (!message.IsHistoricalData && BotModeSwitcher.CanSell())
|
||||
{
|
||||
|
@ -1010,7 +1152,7 @@ INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullS
|
|||
|
||||
}
|
||||
|
||||
if (result[TradingEvent.DowntrendEnd] >= Constants.UppingCoefficient)
|
||||
if (result[TradingEvent.DowntrendEnd] >= Constants.UppingCoefficient * 10)
|
||||
{
|
||||
if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase())
|
||||
{
|
||||
|
@ -1069,7 +1211,7 @@ INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullS
|
|||
}, false);
|
||||
}
|
||||
|
||||
private async Task LogPrice(string figi, string ticker,DateTime time, decimal value, string processor)
|
||||
private async Task LogPrice(string figi, string ticker, DateTime time, decimal value, string processor)
|
||||
{
|
||||
await _tradeDataProvider.LogPrice(new ProcessedPrice()
|
||||
{
|
||||
|
@ -1355,6 +1497,40 @@ INewPrice message, int windowMaxSize, decimal? uptrendStartingDetectionMeanfullS
|
|||
return Task.FromResult(res.ToImmutableDictionary());
|
||||
}
|
||||
|
||||
|
||||
private async Task<ImmutableDictionary<TradingEvent, decimal>> GetCorrelationsMods(INewPrice message)
|
||||
{
|
||||
var res = GetInitDict(1);
|
||||
|
||||
return res.ToImmutableDictionary();
|
||||
if (PirsonZeroCrossings.TryGetValue(message.Figi, out var pir))
|
||||
{
|
||||
if (PricesZeroCrossingsUp.TryGetValue(message.Figi, out var prU))
|
||||
{
|
||||
var dt1 = message.Time - prU;
|
||||
var dt2 = message.Time - pir;
|
||||
|
||||
if (dt1 < TimeSpan.FromMinutes(0.5) && dt2 < TimeSpan.FromMinutes(0.5))
|
||||
{
|
||||
//res[TradingEvent.DowntrendStart] = Constants.UppingCoefficient;
|
||||
res[TradingEvent.UptrendStart] = Constants.UppingCoefficient;
|
||||
}
|
||||
}
|
||||
if (PricesZeroCrossingsDown.TryGetValue(message.Figi, out var prD))
|
||||
{
|
||||
var dt1 = message.Time - prD;
|
||||
var dt2 = message.Time - pir;
|
||||
|
||||
if (dt1 < TimeSpan.FromMinutes(0.5) && dt2 < TimeSpan.FromMinutes(0.5))
|
||||
{
|
||||
res[TradingEvent.DowntrendStart] = Constants.UppingCoefficient;
|
||||
//res[TradingEvent.UptrendStart] = Constants.UppingCoefficient;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
private async Task<ImmutableDictionary<TradingEvent, decimal>> GetSellsDiffsMods(INewPrice message)
|
||||
{
|
||||
var res = GetInitDict(1);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"Token": "",
|
||||
"ManagingAccountNamePatterns": [ "автотрейд" ],
|
||||
"DataRecievingInstrumentsFigis": [ "BBG004730N88", "FUTIMOEXF000", "FUTGMKN09250", "FUTBR1025000", "FUTNG0925000", "FUTNASD09250" ],
|
||||
"TradingInstrumentsFigis": [ "FUTIMOEXF000" ],
|
||||
"TradingInstrumentsFigis": [ "FUTIMOEXF000", "BBG004730N88" ],
|
||||
"FutureComission": 0.0025,
|
||||
"ShareComission": 0.0004,
|
||||
"AccountCashPart": 0.05,
|
||||
|
|
Loading…
Reference in New Issue