Compare commits

...

3 Commits

Author SHA1 Message Date
vlad zverzhkhovskiy 7d2618dd54 фикс подсчёта профита
test / deploy_trader_prod (push) Successful in 57s Details
2025-09-09 11:35:02 +03:00
vlad zverzhkhovskiy 4d898e376a удалил запрос последних цен 2025-09-09 10:51:02 +03:00
vlad zverzhkhovskiy c0e29c06a5 code cleanup 2025-09-09 10:48:18 +03:00
9 changed files with 43 additions and 64 deletions

View File

@ -10,10 +10,10 @@
return (x, y);
}
public static (bool res,DateTime x, decimal y) IsLinesCrossing(DateTime time1, DateTime time2, decimal val1_1, decimal val1_2, decimal val2_1, decimal val2_2)
public static (bool res, DateTime x, decimal y) IsLinesCrossing(DateTime time1, DateTime time2, decimal val1_1, decimal val1_2, decimal val2_1, decimal val2_2)
{
var dtime = (decimal)(time2 - time1).TotalSeconds;
if (dtime == 0) return (false, DateTime.MinValue,0);
if (dtime == 0) return (false, DateTime.MinValue, 0);
var dval1 = val1_2 - val1_1;
var k1 = dval1 / dtime;
var b1 = val1_1;

View File

@ -20,7 +20,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
return (startTime, sum / count);
}
public static (TradingEvent events, decimal bigWindowAv, decimal smallWindowAv) CheckByWindowAverageMean(DateTime[] timestamps, decimal[] prices, int size, int smallWindow, int bigWindow, TimeSpan timeForUptreandStart, decimal meanfullStep = 3m)
public static (TradingEvent events, decimal bigWindowAv, decimal smallWindowAv) CheckByWindowAverageMean(DateTime[] timestamps, decimal[] prices, int size, int smallWindow, int bigWindow, TimeSpan timeForUptreandStart, decimal downtrendStartingDetectionMeanfullStep = 3m, decimal uptrendEndingDetectionMeanfullStep = 3m)
{
var res = TradingEvent.None;
var bigWindowAv = 0m;
@ -63,7 +63,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
twavbs[i2 + 1]);
if (shift == 1 && !isCrossing.res) //если нет пересечения скользящих средний с окном 120 и 15 секунд между
//текущей и предыдущей точкой - можно не продолжать выполнение.
//текущей и предыдущей точкой - можно не продолжать выполнение.
{
break;
}
@ -94,7 +94,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2])
{
if (diffTotal >= meanfullStep
if (diffTotal >= uptrendEndingDetectionMeanfullStep
&& times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart)
{
res |= TradingEvent.UptrendEnd;
@ -112,7 +112,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
// если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта
if (twavss[size - 1] >= twavbs[size - 1] && twavss[size - 2] < twavbs[size - 2])
{
if (pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]] <= - meanfullStep
if (pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]] <= -downtrendStartingDetectionMeanfullStep
&& times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart)
{
res |= TradingEvent.UptrendStart;

View File

@ -1,6 +1,4 @@
using System;
namespace KLHZ.Trader.Core.Math.Declisions.Utils
namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
public static class ShapeAreaCalculator
{

View File

@ -55,9 +55,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
try
{
//_ = SubscribeUpdates();
if (_exchangeDataRecievingEnabled)
{
await SubscribePrices();
_ = SubscribePrices();
}
await Task.Delay(1000);
}
@ -68,15 +69,27 @@ namespace KLHZ.Trader.Core.Exchange.Services
}
}
private async Task SubscribeUpdates()
{
var req = new TradesStreamRequest();
foreach (var a in _tradeDataProvider.Accounts)
{
req.Accounts.Add(a.Key);
}
using var stream = _investApiClient.OrdersStream.TradesStream(req);
await foreach (var response in stream.ResponseStream.ReadAllAsync())
{
if (response.OrderTrades != null)
{
}
}
}
private async Task SubscribePrices()
{
using var stream = _investApiClient.MarketDataStream.MarketDataStream();
//var request = new SubscribeLastPriceRequest
//{
// SubscriptionAction = SubscriptionAction.Subscribe
//};
var tradesRequest = new SubscribeTradesRequest
{
SubscriptionAction = SubscriptionAction.Subscribe
@ -89,12 +102,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
foreach (var f in _instrumentsFigis)
{
//request.Instruments.Add(
// new LastPriceInstrument()
// {
// InstrumentId = f
// });
tradesRequest.Instruments.Add(
new TradeInstrument()
{
@ -109,11 +116,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
});
}
//await stream.RequestStream.WriteAsync(new MarketDataRequest
//{
// SubscribeLastPriceRequest = request,
//});
await stream.RequestStream.WriteAsync(new MarketDataRequest
{
SubscribeTradesRequest = tradesRequest,
@ -129,20 +131,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
var lastWrite = DateTime.UtcNow;
await foreach (var response in stream.ResponseStream.ReadAllAsync())
{
//if (response.LastPrice != null)
//{
// var message = new PriceChange()
// {
// Figi = response.LastPrice.Figi,
// Ticker = _tradeDataProvider.GetTickerByFigi(response.LastPrice.Figi),
// Time = response.LastPrice.Time.ToDateTime().ToUniversalTime(),
// Value = response.LastPrice.Price,
// IsHistoricalData = false,
// };
// await _eventBus.Broadcast(message);
// pricesBuffer.Add(message);
//}
if (response.Trade != null)
{
var message = new PriceChange()

View File

@ -129,7 +129,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
AccountId = asset.AccountId,
Figi = message.Figi,
CommandType = asset.Count < 0? Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketBuy
CommandType = asset.Count < 0 ? Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketBuy
: Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketSell,
Count = (long)asset.Count,
RecomendPrice = null,
@ -145,14 +145,9 @@ namespace KLHZ.Trader.Core.Exchange.Services
INewPrice message, int windowMaxSize)
{
var res = TradingEvent.None;
var resultMoveAvFull = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, windowMaxSize, 25, 120, TimeSpan.FromSeconds(20), 1.5m);
//var resultLongClose = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, windowMaxSize, 15, 120, 1.5m).events;
var resultMoveAvFull = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices,
windowMaxSize, 25, 120, TimeSpan.FromSeconds(20), 1m, 1.5m);
//ar uptrendStarts = LocalTrends.CheckByLocalTrends(data.timestamps, data.prices, TimeSpan.FromSeconds(120), TimeSpan.FromSeconds(20), 1.5m, 15);
//res |= (uptrendStarts & TradingEvent.UptrendStart);
//res |= resultLongClose;
res |= resultMoveAvFull.events;
if (resultMoveAvFull.bigWindowAv != 0)
@ -160,12 +155,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
await LogPrice(message, _bigWindowProcessor, resultMoveAvFull.bigWindowAv);
await LogPrice(message, _smallWindowProcessor, resultMoveAvFull.smallWindowAv);
}
if ((resultMoveAvFull.events & TradingEvent.StopBuy) == TradingEvent.StopBuy)
{
var stopTo = (message.IsHistoricalData ? message.Time : DateTime.UtcNow).AddMinutes(_buyStopLength / 2);
//OpeningStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
//await LogDeclision(DeclisionTradeAction.StopBuy, message);
}
if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart
&& !OpeningStops.TryGetValue(message.Figi, out _)
@ -180,7 +169,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
var max = fullData.prices.Max();
var min = fullData.prices.Min();
if (max - min < 15 && fullData.prices.Last() - fullData.prices.First() < 4 && fullData.prices.Last() - fullData.prices.First()>-4)
if (max - min < 15 && fullData.prices.Last() - fullData.prices.First() < 4 && fullData.prices.Last() - fullData.prices.First() > -4)
{
if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase())
{
@ -221,7 +210,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi);
var loggedDeclisions = 0;
if (!message.IsHistoricalData && BotModeSwitcher.CanSell())
if (BotModeSwitcher.CanSell())
{
var assetsForClose = _tradeDataProvider.Accounts
.SelectMany(a => a.Value.Assets.Values)

View File

@ -1,5 +1,4 @@
using Google.Protobuf.WellKnownTypes;
using KLHZ.Trader.Core.Contracts.Declisions.Interfaces;
using KLHZ.Trader.Core.Contracts.Declisions.Interfaces;
using KLHZ.Trader.Core.Contracts.Messaging.Dtos;
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
using KLHZ.Trader.Core.DataLayer;
@ -166,7 +165,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
_ = WritePricesTask();
}
catch(Exception ex)
catch (Exception ex)
{
}

View File

@ -4,7 +4,13 @@
{
public static decimal CaclProfit(decimal openPrice, decimal closePrice, decimal comission, decimal leverage, bool isShort)
{
var diff = ((isShort ? (closePrice - openPrice) : (openPrice - closePrice)) - closePrice * comission - openPrice * comission) * leverage;
var summComission = closePrice * comission + openPrice * comission;
var priceDiff = closePrice - openPrice;
if (isShort)
{
priceDiff *= -1;
}
var diff = priceDiff * leverage - summComission;
return diff;
}
}

View File

@ -21,7 +21,7 @@ namespace KLHZ.Trader.Core.TG.Services
private readonly TraderDataProvider _traderDataProvider;
public BotMessagesHandler(IDataBus eventBus, IOptions<TgBotConfig> options, ILogger<BotMessagesHandler> logger, TraderDataProvider traderDataProvider)
{
_traderDataProvider = traderDataProvider;
_traderDataProvider = traderDataProvider;
_logger = logger;
_eventBus = eventBus;
_admins = ImmutableArray.CreateRange(options.Value.Admins);
@ -79,7 +79,7 @@ namespace KLHZ.Trader.Core.TG.Services
{
var assets = await _traderDataProvider.GetAssetsByFigi("FUTIMOEXF000");
foreach(var asset in assets)
foreach (var asset in assets)
{
if (asset.Count > 0)
{

View File

@ -1,7 +1,6 @@
using KLHZ.Trader.Core.Contracts.Messaging.Dtos;
using KLHZ.Trader.Core.Contracts.Messaging.Interfaces;
using KLHZ.Trader.Core.DataLayer;
using KLHZ.Trader.Core.DataLayer.Entities.Prices;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -25,7 +24,7 @@ namespace KLHZ.Trader.Service.Controllers
{
try
{
var time = DateTime.UtcNow.AddMinutes(-40);
var time = DateTime.UtcNow.AddMinutes(-35);
using var context1 = await _dbContextFactory.CreateDbContextAsync();
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var data = await context1.PriceChanges