Применение соотношения продаж и покупок сбера
parent
2b9f7cf332
commit
efb6f8b64f
|
@ -4,7 +4,7 @@
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
_1_Minute = 1,
|
_1_Minute = 1,
|
||||||
_2_Minutes = 2,
|
_5_Minutes = 2,
|
||||||
_15_Minutes = 15,
|
_15_Minutes = 15,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Dtos.FFT.Enums
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Middle = 1,
|
Middle = 1,
|
||||||
UpperThen20Decil = 10,
|
UpperThen30Decil = 10,
|
||||||
LowerThenMediana = -50,
|
LowerThenMediana = -50,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Dtos.FFT
|
||||||
public decimal Max { get; init; }
|
public decimal Max { get; init; }
|
||||||
public decimal Min { get; init; }
|
public decimal Min { get; init; }
|
||||||
public decimal Mediana { get; init; }
|
public decimal Mediana { get; init; }
|
||||||
public decimal Upper20Decil { get; init; }
|
public decimal Upper30Decil { get; init; }
|
||||||
public decimal Lower20Decil { get; init; }
|
public decimal Lower20Decil { get; init; }
|
||||||
public DateTime LastTime { get; init; }
|
public DateTime LastTime { get; init; }
|
||||||
public DateTime StartTime { get; init; }
|
public DateTime StartTime { get; init; }
|
||||||
|
|
|
@ -43,9 +43,9 @@ namespace KLHZ.Trader.Core.Math.Declisions.Dtos
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case TimeWindowCacheType._2_Minutes:
|
case TimeWindowCacheType._5_Minutes:
|
||||||
{
|
{
|
||||||
return TimeSpan.FromMinutes(2);
|
return TimeSpan.FromMinutes(5);
|
||||||
}
|
}
|
||||||
case TimeWindowCacheType._15_Minutes:
|
case TimeWindowCacheType._15_Minutes:
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
||||||
private readonly decimal[] Prices = new decimal[_arrayMaxLength];
|
private readonly decimal[] Prices = new decimal[_arrayMaxLength];
|
||||||
private readonly DateTime[] Timestamps = new DateTime[_arrayMaxLength];
|
private readonly DateTime[] Timestamps = new DateTime[_arrayMaxLength];
|
||||||
private readonly ConcurrentDictionary<string, TimeWindowCacheItem> _1_minTimeWindows = new();
|
private readonly ConcurrentDictionary<string, TimeWindowCacheItem> _1_minTimeWindows = new();
|
||||||
private readonly ConcurrentDictionary<string, TimeWindowCacheItem> _2_minTimeWindows = new();
|
private readonly ConcurrentDictionary<string, TimeWindowCacheItem> _5_minTimeWindows = new();
|
||||||
private readonly ConcurrentDictionary<string, TimeWindowCacheItem> _15_minTimeWindows = new();
|
private readonly ConcurrentDictionary<string, TimeWindowCacheItem> _15_minTimeWindows = new();
|
||||||
|
|
||||||
private int _length = 0;
|
private int _length = 0;
|
||||||
|
@ -85,9 +85,9 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
|
||||||
{
|
{
|
||||||
switch (timeWindowCacheType)
|
switch (timeWindowCacheType)
|
||||||
{
|
{
|
||||||
case TimeWindowCacheType._2_Minutes:
|
case TimeWindowCacheType._5_Minutes:
|
||||||
{
|
{
|
||||||
return _2_minTimeWindows;
|
return _5_minTimeWindows;
|
||||||
}
|
}
|
||||||
case TimeWindowCacheType._15_Minutes:
|
case TimeWindowCacheType._15_Minutes:
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,9 +11,9 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||||||
{
|
{
|
||||||
var value = (decimal)CalcAmplitude(fftData.Harmonics, fftData.StartTime, timestamp);
|
var value = (decimal)CalcAmplitude(fftData.Harmonics, fftData.StartTime, timestamp);
|
||||||
var value2 = (decimal)CalcExtremum(fftData.Harmonics, fftData.StartTime, timestamp);
|
var value2 = (decimal)CalcExtremum(fftData.Harmonics, fftData.StartTime, timestamp);
|
||||||
if (value > fftData.Upper20Decil)
|
if (value > fftData.Upper30Decil)
|
||||||
{
|
{
|
||||||
return ValueAmplitudePosition.UpperThen20Decil;
|
return ValueAmplitudePosition.UpperThen30Decil;
|
||||||
}
|
}
|
||||||
else if (value < fftData.Mediana)
|
else if (value < fftData.Mediana)
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||||||
LastTime = timestamps[timestamps.Length - 1],
|
LastTime = timestamps[timestamps.Length - 1],
|
||||||
StartTime = startTime,
|
StartTime = startTime,
|
||||||
Mediana = newValues[newValues.Length / 2],
|
Mediana = newValues[newValues.Length / 2],
|
||||||
Upper20Decil = newValues[(int)(newValues.Length * 0.8)],
|
Upper30Decil = newValues[(int)(newValues.Length * 0.7)],
|
||||||
Lower20Decil = newValues[(int)(newValues.Length * 0.2)],
|
Lower20Decil = newValues[(int)(newValues.Length * 0.2)],
|
||||||
Max = newValues.Max(),
|
Max = newValues.Max(),
|
||||||
Min = newValues.Min(),
|
Min = newValues.Min(),
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
internal static class Constants
|
internal static class Constants
|
||||||
{
|
{
|
||||||
internal const string _1minCacheKey = "1min";
|
internal const string _1minCacheKey = "1min";
|
||||||
|
internal const string _1minSellCacheKey = "1min_sell";
|
||||||
|
internal const string _1minBuyCacheKey = "1min_buy";
|
||||||
internal const string BigWindowCrossingAverageProcessor = "Trader_big";
|
internal const string BigWindowCrossingAverageProcessor = "Trader_big";
|
||||||
internal const string SmallWindowCrossingAverageProcessor = "Trader_small";
|
internal const string SmallWindowCrossingAverageProcessor = "Trader_small";
|
||||||
internal const string AreasRelationProcessor = "balancescalc30min";
|
internal const string AreasRelationProcessor = "balancescalc30min";
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
private readonly TraderDataProvider _tradeDataProvider;
|
private readonly TraderDataProvider _tradeDataProvider;
|
||||||
private readonly ILogger<Trader> _logger;
|
private readonly ILogger<Trader> _logger;
|
||||||
private readonly ConcurrentDictionary<string, DateTime> LongOpeningStops = new();
|
private readonly ConcurrentDictionary<string, DateTime> LongOpeningStops = new();
|
||||||
|
private readonly ConcurrentDictionary<string, DateTime> LongClosingStops = new();
|
||||||
private readonly ConcurrentDictionary<string, DateTime> ShortClosingStops = new();
|
private readonly ConcurrentDictionary<string, DateTime> ShortClosingStops = new();
|
||||||
private readonly ConcurrentDictionary<string, InstrumentSettings> Leverages = new();
|
private readonly ConcurrentDictionary<string, InstrumentSettings> Leverages = new();
|
||||||
|
|
||||||
|
@ -105,9 +106,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
position = FFT.Check(fft, message.Time);
|
position = FFT.Check(fft, message.Time);
|
||||||
if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.UpperThen20Decil)
|
if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.UpperThen30Decil)
|
||||||
{
|
{
|
||||||
await LogPrice(message, "upper10percent", message.Value);
|
|
||||||
await LogPrice(message, "upper30percent", message.Value);
|
await LogPrice(message, "upper30percent", message.Value);
|
||||||
}
|
}
|
||||||
if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.LowerThenMediana)
|
if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.LowerThenMediana)
|
||||||
|
@ -155,6 +155,36 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
list.Clear();
|
list.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (message.Figi == "BBG004730N88")
|
||||||
|
{
|
||||||
|
if (message.Direction == 1)
|
||||||
|
{
|
||||||
|
await _tradeDataProvider.AddDataTo5MinuteWindowCache(message.Figi, Constants._1minBuyCacheKey, new Contracts.Declisions.Dtos.CachedValue()
|
||||||
|
{
|
||||||
|
Time = message.Time,
|
||||||
|
Value = (decimal)message.Count
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (message.Direction == 2)
|
||||||
|
{
|
||||||
|
await _tradeDataProvider.AddDataTo5MinuteWindowCache(message.Figi, Constants._1minSellCacheKey, new Contracts.Declisions.Dtos.CachedValue()
|
||||||
|
{
|
||||||
|
Time = message.Time,
|
||||||
|
Value = (decimal)message.Count
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
var sberSells = await _tradeDataProvider.GetDataFrom5MinuteWindowCache("BBG004730N88", Constants._1minSellCacheKey);
|
||||||
|
var sberBuys = await _tradeDataProvider.GetDataFrom5MinuteWindowCache("BBG004730N88", Constants._1minBuyCacheKey);
|
||||||
|
var sells = sberSells.Sum(s => s.Value);
|
||||||
|
var buys = sberBuys.Sum(s => s.Value);
|
||||||
|
var su = sells + buys;
|
||||||
|
if (su != 0)
|
||||||
|
{
|
||||||
|
await LogPrice(message, "sellsbuysbalance", (sells / su - 0.5m)*2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_tradingInstrumentsFigis.Contains(message.Figi))
|
if (_tradingInstrumentsFigis.Contains(message.Figi))
|
||||||
{
|
{
|
||||||
var currentTime = message.IsHistoricalData ? message.Time : DateTime.UtcNow;
|
var currentTime = message.IsHistoricalData ? message.Time : DateTime.UtcNow;
|
||||||
|
@ -314,6 +344,14 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sberSells = await _tradeDataProvider.GetDataFrom5MinuteWindowCache("BBG004730N88", Constants._1minSellCacheKey);
|
||||||
|
var sberBuys = await _tradeDataProvider.GetDataFrom5MinuteWindowCache("BBG004730N88", Constants._1minBuyCacheKey);
|
||||||
|
var sells = sberSells.Sum(s => s.Value);
|
||||||
|
var buys = sberBuys.Sum(s => s.Value);
|
||||||
|
var su = sells + buys;
|
||||||
|
var dsell = (sells / su - 0.5m) * 2;
|
||||||
|
|
||||||
|
|
||||||
var mavTask = CheckByWindowAverageMean(data, message, windowMaxSize);
|
var mavTask = CheckByWindowAverageMean(data, message, windowMaxSize);
|
||||||
var mavTaskShorts = CheckByWindowAverageMeanForShotrs(data, message, windowMaxSize);
|
var mavTaskShorts = CheckByWindowAverageMeanForShotrs(data, message, windowMaxSize);
|
||||||
var ltTask = CheckByLocalTrends(data, message, windowMaxSize);
|
var ltTask = CheckByLocalTrends(data, message, windowMaxSize);
|
||||||
|
@ -328,7 +366,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart
|
if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart
|
||||||
&& !LongOpeningStops.ContainsKey(message.Figi)
|
&& !LongOpeningStops.ContainsKey(message.Figi)
|
||||||
&& trendTask.Result.HasValue
|
&& trendTask.Result.HasValue
|
||||||
&& System.Math.Abs(trendTask.Result.Value)<6
|
&& trendTask.Result.Value > -5
|
||||||
&& state == ExchangeState.Open
|
&& state == ExchangeState.Open
|
||||||
&& areasTask.Result.HasValue
|
&& areasTask.Result.HasValue
|
||||||
&& (areasTask.Result.Value >= 20 && areasTask.Result.Value < 75)
|
&& (areasTask.Result.Value >= 20 && areasTask.Result.Value < 75)
|
||||||
|
@ -371,7 +409,9 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
|
|
||||||
await LogDeclision(DeclisionTradeAction.OpenLong, message);
|
await LogDeclision(DeclisionTradeAction.OpenLong, message);
|
||||||
}
|
}
|
||||||
if ((res & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd && positionTask.Result != ValueAmplitudePosition.LowerThenMediana)
|
if ((res & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
|
||||||
|
{
|
||||||
|
if (dsell < 0.1m)
|
||||||
{
|
{
|
||||||
if (!message.IsHistoricalData && BotModeSwitcher.CanSell())
|
if (!message.IsHistoricalData && BotModeSwitcher.CanSell())
|
||||||
{
|
{
|
||||||
|
@ -394,10 +434,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value,
|
profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value,
|
||||||
GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0);
|
GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0);
|
||||||
}
|
}
|
||||||
var stoppingKey = message.Figi + asset.AccountId;
|
|
||||||
if (profit > 0)
|
if (profit > 0)
|
||||||
{
|
{
|
||||||
//ClosingStops[stoppingKey] = DateTime.UtcNow.AddSeconds(30);
|
LongClosingStops[message.Figi] = message.Time.AddSeconds(30);
|
||||||
var command = new TradeCommand()
|
var command = new TradeCommand()
|
||||||
{
|
{
|
||||||
AccountId = asset.AccountId,
|
AccountId = asset.AccountId,
|
||||||
|
@ -421,9 +461,11 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
await LogDeclision(DeclisionTradeAction.CloseLong, message);
|
await LogDeclision(DeclisionTradeAction.CloseLong, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if ((mavTaskShorts.Result & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
|
if ((mavTaskShorts.Result & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
|
||||||
{
|
{
|
||||||
if (trendTask.Result.HasValue && trendTask.Result.Value < -3)
|
if (trendTask.Result.HasValue && trendTask.Result.Value < -4)
|
||||||
{
|
{
|
||||||
if (!message.IsHistoricalData)
|
if (!message.IsHistoricalData)
|
||||||
{
|
{
|
||||||
|
@ -541,6 +583,13 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
ShortClosingStops.TryRemove(message.Figi, out _);
|
ShortClosingStops.TryRemove(message.Figi, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (LongClosingStops.TryGetValue(message.Figi, out var dt3))
|
||||||
|
{
|
||||||
|
if (dt3 < currentTime)
|
||||||
|
{
|
||||||
|
LongClosingStops.TryRemove(message.Figi, out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LogPrice(INewPrice message, string processor, decimal value)
|
private async Task LogPrice(INewPrice message, string processor, decimal value)
|
||||||
|
|
|
@ -126,6 +126,16 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
await _historyCash[figi].AddDataToTimeWindowCache(key, data, TimeWindowCacheType._1_Minute);
|
await _historyCash[figi].AddDataToTimeWindowCache(key, data, TimeWindowCacheType._1_Minute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask AddDataTo5MinuteWindowCache(string figi, string key, CachedValue data)
|
||||||
|
{
|
||||||
|
if (!_historyCash.TryGetValue(figi, out var unit))
|
||||||
|
{
|
||||||
|
unit = new PriceHistoryCacheUnit2(figi);
|
||||||
|
_historyCash.TryAdd(figi, unit);
|
||||||
|
}
|
||||||
|
await _historyCash[figi].AddDataToTimeWindowCache(key, data, TimeWindowCacheType._5_Minutes);
|
||||||
|
}
|
||||||
|
|
||||||
public ValueTask<CachedValue[]> GetDataFrom1MinuteWindowCache(string figi, string key)
|
public ValueTask<CachedValue[]> GetDataFrom1MinuteWindowCache(string figi, string key)
|
||||||
{
|
{
|
||||||
if (_historyCash.TryGetValue(figi, out var cahcheItem))
|
if (_historyCash.TryGetValue(figi, out var cahcheItem))
|
||||||
|
@ -135,6 +145,15 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
return ValueTask.FromResult(Array.Empty<CachedValue>());
|
return ValueTask.FromResult(Array.Empty<CachedValue>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ValueTask<CachedValue[]> GetDataFrom5MinuteWindowCache(string figi, string key)
|
||||||
|
{
|
||||||
|
if (_historyCash.TryGetValue(figi, out var cahcheItem))
|
||||||
|
{
|
||||||
|
return cahcheItem.GetDataFromTimeWindowCache(key, TimeWindowCacheType._5_Minutes);
|
||||||
|
}
|
||||||
|
return ValueTask.FromResult(Array.Empty<CachedValue>());
|
||||||
|
}
|
||||||
|
|
||||||
public async ValueTask AddOrderbook(IOrderbook orderbook)
|
public async ValueTask AddOrderbook(IOrderbook orderbook)
|
||||||
{
|
{
|
||||||
if (!_historyCash.TryGetValue(orderbook.Figi, out var unit))
|
if (!_historyCash.TryGetValue(orderbook.Figi, out var unit))
|
||||||
|
|
|
@ -26,20 +26,24 @@ namespace KLHZ.Trader.Service.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task Run(string figi)
|
public async Task Run()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var figi1 = "FUTIMOEXF000";
|
||||||
|
//var figi1 = "BBG004730N88";
|
||||||
|
var figi2 = "BBG004730N88";
|
||||||
|
//var figi2 = "FUTIMOEXF000";
|
||||||
var time1 = DateTime.UtcNow.AddDays(-16.5);
|
var time1 = DateTime.UtcNow.AddDays(-16.5);
|
||||||
//var time2 = DateTime.UtcNow.AddMinutes(18);
|
//var time2 = DateTime.UtcNow.AddMinutes(18);
|
||||||
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
||||||
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||||
var data = await context1.PriceChanges
|
var data = await context1.PriceChanges
|
||||||
.Where(c => c.Figi == figi && c.Time >= time1)
|
.Where(c => (c.Figi == figi1 || c.Figi == figi2) && c.Time >= time1)
|
||||||
.OrderBy(c => c.Time)
|
.OrderBy(c => c.Time)
|
||||||
.Select(c => new NewPriceMessage()
|
.Select(c => new NewPriceMessage()
|
||||||
{
|
{
|
||||||
Figi = figi,
|
Figi = c.Figi,
|
||||||
Ticker = c.Ticker,
|
Ticker = c.Ticker,
|
||||||
Time = c.Time,
|
Time = c.Time,
|
||||||
Value = c.Value,
|
Value = c.Value,
|
||||||
|
|
Loading…
Reference in New Issue