Доработка модуля решений
test / deploy_trader_prod (push) Successful in 49s
Details
test / deploy_trader_prod (push) Successful in 49s
Details
parent
d045f9b082
commit
d15281f67e
|
@ -18,78 +18,86 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||||||
return (startTime, sum / count);
|
return (startTime, sum / count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TradingEvent CheckByWindowAverageMean(DateTime[] timestamps, decimal[] prices, int size, int smallWindow, int bigWindow, decimal meanfullStep = 3m)
|
public static (TradingEvent events, decimal bigWindowAv, decimal smallWindowAv) CheckByWindowAverageMean(DateTime[] timestamps, decimal[] prices, int size, int smallWindow, int bigWindow, decimal meanfullStep = 3m)
|
||||||
{
|
{
|
||||||
var res = TradingEvent.None;
|
var res = TradingEvent.None;
|
||||||
if (timestamps.Length < size)
|
var bigWindowAv = 0m;
|
||||||
|
var smallWindowAv = 0m;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return res;
|
var pricesForFinalComparison = new decimal[size];
|
||||||
}
|
var twavss = new decimal[size];
|
||||||
var pricesForFinalComparison = new decimal[size];
|
var twavbs = new decimal[size];
|
||||||
var twavss = new decimal[size];
|
var times = new DateTime[size];
|
||||||
var twavbs = new decimal[size];
|
|
||||||
var times = new DateTime[size];
|
|
||||||
|
|
||||||
|
for (int shift = 0; shift < size; shift++)
|
||||||
for (int shift = 0; shift < size; shift++)
|
|
||||||
{
|
|
||||||
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;
|
var twavs = CalcTimeWindowAverageValue(timestamps, prices, smallWindow, shift);
|
||||||
return res;
|
var twavb = CalcTimeWindowAverageValue(timestamps, prices, bigWindow, shift);
|
||||||
}
|
pricesForFinalComparison[size - 1 - shift] = prices[prices.Length - 1 - shift];
|
||||||
if (shift > 0)
|
if (shift == 0)
|
||||||
{
|
|
||||||
var i1 = size - 1 - shift;
|
|
||||||
var i2 = size - shift;
|
|
||||||
var isCrossing = Lines.IsLinesCrossing(
|
|
||||||
times[i1],
|
|
||||||
times[i2],
|
|
||||||
twavss[i1],
|
|
||||||
twavss[i2],
|
|
||||||
twavbs[i1],
|
|
||||||
twavbs[i2]);
|
|
||||||
|
|
||||||
if (shift == 1 && !isCrossing) //если нет пересечения скользящих средний с окном 120 и 15 секунд между
|
|
||||||
//текущей и предыдущей точкой - можно не продолжать выполнение.
|
|
||||||
{
|
{
|
||||||
break;
|
bigWindowAv = twavb.value;
|
||||||
|
smallWindowAv = twavs.value;
|
||||||
}
|
}
|
||||||
if (shift > 1 && isCrossing)
|
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)
|
||||||
{
|
{
|
||||||
// если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта
|
res |= TradingEvent.StopBuy;
|
||||||
if (twavbs[size - 1] <= twavss[size - 1] && twavbs[size - 2] > twavss[size - 2])
|
return (res, bigWindowAv, smallWindowAv);
|
||||||
{
|
}
|
||||||
if (pricesForFinalComparison[size - 1 - shift] - pricesForFinalComparison[size - 1] >= meanfullStep)
|
if (shift > 0)
|
||||||
{
|
{
|
||||||
res |= TradingEvent.LongOpen;
|
var i1 = size - 1 - shift;
|
||||||
res |= TradingEvent.ShortClose;
|
var i2 = size - shift;
|
||||||
break;
|
var isCrossing = Lines.IsLinesCrossing(
|
||||||
}
|
times[i1],
|
||||||
}
|
times[i2],
|
||||||
|
twavss[i1],
|
||||||
|
twavss[i2],
|
||||||
|
twavbs[i1],
|
||||||
|
twavbs[i2]);
|
||||||
|
|
||||||
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
|
if (shift == 1 && !isCrossing) //если нет пересечения скользящих средний с окном 120 и 15 секунд между
|
||||||
if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2])
|
//текущей и предыдущей точкой - можно не продолжать выполнение.
|
||||||
{
|
{
|
||||||
if (pricesForFinalComparison[size - 1 - shift] - pricesForFinalComparison[size - 1] <= -meanfullStep)
|
break;
|
||||||
|
}
|
||||||
|
if (shift > 1 && isCrossing)
|
||||||
|
{
|
||||||
|
// если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта
|
||||||
|
if (twavbs[size - 1] <= twavss[size - 1] && twavbs[size - 2] > twavss[size - 2])
|
||||||
{
|
{
|
||||||
res |= TradingEvent.LongClose;
|
if (pricesForFinalComparison[size - 1 - shift] - pricesForFinalComparison[size - 1] >= meanfullStep)
|
||||||
res |= TradingEvent.ShortOpen;
|
{
|
||||||
break;
|
res |= TradingEvent.LongOpen;
|
||||||
|
res |= TradingEvent.ShortClose;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
|
||||||
|
if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2])
|
||||||
|
{
|
||||||
|
if (pricesForFinalComparison[size - 1 - shift] - pricesForFinalComparison[size - 1] <= -meanfullStep)
|
||||||
|
{
|
||||||
|
res |= TradingEvent.LongClose;
|
||||||
|
res |= TradingEvent.ShortOpen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
return res;
|
}
|
||||||
|
return (res, bigWindowAv, smallWindowAv);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,10 @@ namespace KLHZ.Trader.Core.DataLayer.Entities.Declisions
|
||||||
|
|
||||||
[Column("price")]
|
[Column("price")]
|
||||||
public decimal Price { get; set; }
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
[Column("value")]
|
||||||
|
public decimal? Value { get; set; }
|
||||||
|
|
||||||
[Column("action")]
|
[Column("action")]
|
||||||
public DeclisionTradeAction Action { get; set; }
|
public DeclisionTradeAction Action { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ using KLHZ.Trader.Core.Contracts.Messaging.Interfaces;
|
||||||
using KLHZ.Trader.Core.DataLayer;
|
using KLHZ.Trader.Core.DataLayer;
|
||||||
using KLHZ.Trader.Core.DataLayer.Entities.Declisions;
|
using KLHZ.Trader.Core.DataLayer.Entities.Declisions;
|
||||||
using KLHZ.Trader.Core.DataLayer.Entities.Declisions.Enums;
|
using KLHZ.Trader.Core.DataLayer.Entities.Declisions.Enums;
|
||||||
|
using KLHZ.Trader.Core.DataLayer.Entities.Prices;
|
||||||
using KLHZ.Trader.Core.Exchange.Extentions;
|
using KLHZ.Trader.Core.Exchange.Extentions;
|
||||||
using KLHZ.Trader.Core.Exchange.Models;
|
using KLHZ.Trader.Core.Exchange.Models;
|
||||||
using KLHZ.Trader.Core.Math.Declisions.Services.Cache;
|
using KLHZ.Trader.Core.Math.Declisions.Services.Cache;
|
||||||
|
@ -115,6 +116,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
|
|
||||||
private async Task ProcessPrices()
|
private async Task ProcessPrices()
|
||||||
{
|
{
|
||||||
|
var declisionsForSave = new List<Declision>();
|
||||||
|
var processedPrices = new List<ProcessedPrice>();
|
||||||
while (await _pricesChannel.Reader.WaitToReadAsync())
|
while (await _pricesChannel.Reader.WaitToReadAsync())
|
||||||
{
|
{
|
||||||
var message = await _pricesChannel.Reader.ReadAsync();
|
var message = await _pricesChannel.Reader.ReadAsync();
|
||||||
|
@ -132,7 +135,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var data = await unit.GetData();
|
var data = await unit.GetData();
|
||||||
var declisionsForSave = new List<Declision>();
|
|
||||||
if (message.Figi == "FUTIMOEXF000")
|
if (message.Figi == "FUTIMOEXF000")
|
||||||
{
|
{
|
||||||
if (unit.Length < 100)
|
if (unit.Length < 100)
|
||||||
|
@ -140,9 +143,58 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BuyStops.TryGetValue(message.Figi, out var dt))
|
||||||
|
{
|
||||||
|
if (dt > (message.IsHistoricalData ? message.Time : DateTime.UtcNow))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BuyStops.TryRemove(message.Figi, out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((unit.BidsCount / unit.AsksCount) < 0.5m || (unit.BidsCount / unit.AsksCount) > 2m)
|
||||||
|
{
|
||||||
|
var stopTo = (message.IsHistoricalData ? message.Time : DateTime.UtcNow).AddMinutes(3);
|
||||||
|
BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
|
||||||
|
declisionsForSave.Add(new Declision()
|
||||||
|
{
|
||||||
|
AccountId = string.Empty,
|
||||||
|
Figi = message.Figi,
|
||||||
|
Ticker = message.Ticker,
|
||||||
|
Price = message.Value,
|
||||||
|
Value = 3,
|
||||||
|
Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||||
|
Action = DeclisionTradeAction.StopBuy,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 15, 120);
|
var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 15, 120);
|
||||||
if ((result & TradingEvent.StopBuy) == TradingEvent.StopBuy)
|
if (result.bigWindowAv != 0)
|
||||||
|
{
|
||||||
|
var priceb = new ProcessedPrice()
|
||||||
|
{
|
||||||
|
Figi = message.Figi,
|
||||||
|
Ticker = message.Ticker,
|
||||||
|
Processor = nameof(Trader) + "_big",
|
||||||
|
Time = message.Time,
|
||||||
|
Value = result.bigWindowAv,
|
||||||
|
};
|
||||||
|
|
||||||
|
var prices = new ProcessedPrice()
|
||||||
|
{
|
||||||
|
Figi = message.Figi,
|
||||||
|
Ticker = message.Ticker,
|
||||||
|
Processor = nameof(Trader) + "_small",
|
||||||
|
Time = message.Time,
|
||||||
|
Value = result.smallWindowAv,
|
||||||
|
};
|
||||||
|
processedPrices.Add(priceb);
|
||||||
|
processedPrices.Add(prices);
|
||||||
|
}
|
||||||
|
if ((result.events & TradingEvent.StopBuy) == TradingEvent.StopBuy)
|
||||||
{
|
{
|
||||||
var stopTo = (message.IsHistoricalData ? message.Time : DateTime.UtcNow).AddMinutes(_buyStopLength);
|
var stopTo = (message.IsHistoricalData ? message.Time : DateTime.UtcNow).AddMinutes(_buyStopLength);
|
||||||
BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
|
BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
|
||||||
|
@ -152,26 +204,15 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
Figi = message.Figi,
|
Figi = message.Figi,
|
||||||
Ticker = message.Ticker,
|
Ticker = message.Ticker,
|
||||||
Price = message.Value,
|
Price = message.Value,
|
||||||
|
Value = (decimal)_buyStopLength,
|
||||||
Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
|
||||||
Action = DeclisionTradeAction.StopBuy,
|
Action = DeclisionTradeAction.StopBuy,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result & TradingEvent.LongOpen) == TradingEvent.LongOpen
|
if ((result.events & TradingEvent.LongOpen) == TradingEvent.LongOpen
|
||||||
&& ((unit.BidsCount / unit.AsksCount) > 0.5m))
|
&& ((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 _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declisionsForSave.Add(new Declision()
|
declisionsForSave.Add(new Declision()
|
||||||
{
|
{
|
||||||
AccountId = string.Empty,
|
AccountId = string.Empty,
|
||||||
|
@ -183,7 +224,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result & TradingEvent.LongClose) == TradingEvent.LongClose)
|
if ((result.events & TradingEvent.LongClose) == TradingEvent.LongClose)
|
||||||
{
|
{
|
||||||
declisionsForSave.Add(new Declision()
|
declisionsForSave.Add(new Declision()
|
||||||
{
|
{
|
||||||
|
@ -196,7 +237,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result & TradingEvent.ShortOpen) == TradingEvent.ShortOpen && (unit.BidsCount / unit.AsksCount < 2))
|
if ((result.events & TradingEvent.ShortOpen) == TradingEvent.ShortOpen && (unit.BidsCount / unit.AsksCount < 2))
|
||||||
{
|
{
|
||||||
declisionsForSave.Add(new Declision()
|
declisionsForSave.Add(new Declision()
|
||||||
{
|
{
|
||||||
|
@ -209,7 +250,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result & TradingEvent.ShortClose) == TradingEvent.ShortClose)
|
if ((result.events & TradingEvent.ShortClose) == TradingEvent.ShortClose)
|
||||||
{
|
{
|
||||||
declisionsForSave.Add(new Declision()
|
declisionsForSave.Add(new Declision()
|
||||||
{
|
{
|
||||||
|
@ -222,14 +263,23 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declisionsForSave.Count > 0)
|
if ((!message.IsHistoricalData && (processedPrices.Count > 0 || declisionsForSave.Count > 0))
|
||||||
|
|| (message.IsHistoricalData && ((processedPrices.Count + declisionsForSave.Count > 10000) || _pricesChannel.Reader.Count == 0)))
|
||||||
{
|
{
|
||||||
using var context = await _dbContextFactory.CreateDbContextAsync();
|
using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||||
|
|
||||||
await context.AddRangeAsync(declisionsForSave);
|
if (processedPrices.Count > 0)
|
||||||
|
{
|
||||||
|
await context.ProcessedPrices.AddRangeAsync(processedPrices);
|
||||||
|
processedPrices.Clear();
|
||||||
|
}
|
||||||
|
if (declisionsForSave.Count > 0)
|
||||||
|
{
|
||||||
|
await context.Declisions.AddRangeAsync(declisionsForSave);
|
||||||
|
declisionsForSave.Clear();
|
||||||
|
}
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
declisionsForSave.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,6 +288,11 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_pricesChannel.Reader.Count == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
alter table declisions add column value decimal default null;
|
|
@ -12,7 +12,7 @@
|
||||||
"ExchangeDataRecievingEnabled": true,
|
"ExchangeDataRecievingEnabled": true,
|
||||||
"Token": "",
|
"Token": "",
|
||||||
"ManagingAccountNamePatterns": [ "автотрейд 1" ],
|
"ManagingAccountNamePatterns": [ "автотрейд 1" ],
|
||||||
"DataRecievingInstrumentsFigis": [ "BBG004730N88", "FUTIMOEXF000", "FUTGMKN09250", "FUTBR1025000" ],
|
"DataRecievingInstrumentsFigis": [ "BBG004730N88", "FUTIMOEXF000", "FUTGMKN09250", "FUTBR1025000", "FUTNG0925000" ],
|
||||||
"TradingInstrumentsFigis": [ "FUTIMOEXF000" ],
|
"TradingInstrumentsFigis": [ "FUTIMOEXF000" ],
|
||||||
"FutureComission": 0.0025,
|
"FutureComission": 0.0025,
|
||||||
"ShareComission": 0.0004,
|
"ShareComission": 0.0004,
|
||||||
|
|
Loading…
Reference in New Issue