Global fix (#9)

* Fix time for candle

* Fix out ouf range

* Fix pnl, fix custom money management

* Clean a bit
This commit is contained in:
Oda
2025-02-04 14:59:39 +07:00
committed by GitHub
parent ff0433c349
commit 0987fa76cf
26 changed files with 153 additions and 139 deletions

View File

@@ -14,7 +14,7 @@ public class PricesFiveMinutesWorker : PricesBaseWorker<PricesFiveMinutesWorker>
pricesService, pricesService,
workerService, workerService,
statisticService, statisticService,
TimeSpan.FromMinutes(2.5), TimeSpan.FromMinutes(1),
WorkerType.PriceFiveMinutes, WorkerType.PriceFiveMinutes,
Timeframe.FiveMinutes Timeframe.FiveMinutes
) )

View File

@@ -20,7 +20,7 @@ public class SpotlightWorker : BaseWorker<SpotlightWorker>
_statisticService = statisticService; _statisticService = statisticService;
} }
protected async override Task Run(CancellationToken cancellationToken) protected override async Task Run(CancellationToken cancellationToken)
{ {
try try
{ {

View File

@@ -1,9 +1,7 @@
using Managing.Application.Abstractions; using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services; using Managing.Application.Abstractions.Services;
using Managing.Application.Hubs; using Managing.Application.Hubs;
using Managing.Core;
using Managing.Domain.Backtests; using Managing.Domain.Backtests;
using Managing.Domain.Candles;
using Managing.Domain.MoneyManagements; using Managing.Domain.MoneyManagements;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;

View File

@@ -107,7 +107,7 @@ public class BotController : ControllerBase
foreach (var bot in bots) foreach (var bot in bots)
{ {
result += $"{bot.Name} : "; result += $"{bot.Name} : ";
result = await _mediator.Send(new StopBotCommand(bot.BotType, bot.Name)); result += await _mediator.Send(new StopBotCommand(bot.BotType, bot.Name));
result += $" |"; result += $" |";
} }
@@ -147,7 +147,7 @@ public class BotController : ControllerBase
foreach (var bot in bots) foreach (var bot in bots)
{ {
result += $"{bot.Name} : "; result += $"{bot.Name} : ";
result = await _mediator.Send(new RestartBotCommand(bot.BotType, bot.Name)); result += await _mediator.Send(new RestartBotCommand(bot.BotType, bot.Name));
result += $" |"; result += $" |";
} }

File diff suppressed because one or more lines are too long

View File

@@ -78,12 +78,12 @@ namespace Managing.Application.Tests
[Theory] [Theory]
[InlineData(TradingExchanges.Ftx, Ticker.ADA, Timeframe.OneDay, -500)] [InlineData(TradingExchanges.Ftx, Ticker.ADA, Timeframe.OneDay, -500)]
public async void Shoud_Return_Signal_On_Macd_Cross(TradingExchanges exchange, Ticker ticker, public async Task Shoud_Return_Signal_On_Macd_Cross(TradingExchanges exchange, Ticker ticker,
Timeframe timeframe, int days) Timeframe timeframe, int days)
{ {
// Arrange // Arrange
var account = GetAccount(exchange); var account = GetAccount(exchange);
var rsiStrategy = new MACDCrossStrategy("unittest", timeframe, 12, 26, 9); var rsiStrategy = new MacdCrossStrategy("unittest", timeframe, 12, 26, 9);
var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe); var candles = await _exchangeService.GetCandles(account, ticker, DateTime.Now.AddDays(days), timeframe);
var resultSignal = new List<Signal>(); var resultSignal = new List<Signal>();

View File

@@ -1,7 +1,6 @@
using Managing.Application.Abstractions.Repositories; using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services; using Managing.Application.Abstractions.Services;
using Managing.Application.Workers.Abstractions; using Managing.Application.Workers.Abstractions;
using Managing.Domain.Candles;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using static Managing.Common.Enums; using static Managing.Common.Enums;

View File

@@ -1,5 +1,4 @@
using Managing.Application.Abstractions; using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services; using Managing.Application.Abstractions.Services;
using Managing.Application.Workers.Abstractions; using Managing.Application.Workers.Abstractions;
using Managing.Domain.Accounts; using Managing.Domain.Accounts;

View File

@@ -139,11 +139,9 @@ namespace Managing.Application.Backtesting
throw new Exception("No candle to backtest"); throw new Exception("No candle to backtest");
} }
var hodlBalances = new Dictionary<DateTime, decimal>();
bot.WalletBalances.Add(candles.FirstOrDefault().Date, balance); bot.WalletBalances.Add(candles.FirstOrDefault().Date, balance);
foreach (var candle in candles) foreach (var candle in candles)
{ {
hodlBalances.Add(candle.Date, candle.Close);
bot.Candles.Add(candle); bot.Candles.Add(candle);
bot.Run(); bot.Run();
} }

View File

@@ -21,7 +21,7 @@ public class LoadBackupBotCommandHandler : IRequestHandler<LoadBackupBotCommand,
public Task<string> Handle(LoadBackupBotCommand request, CancellationToken cancellationToken) public Task<string> Handle(LoadBackupBotCommand request, CancellationToken cancellationToken)
{ {
BotStatus botStatus = BotStatus.Down; BotStatus botStatus = BotStatus.Down;
var backupBots = _botService.GetSavedBots(); var backupBots = _botService.GetSavedBots().ToList();
var activeBots = _botService.GetActiveBots(); var activeBots = _botService.GetActiveBots();
var result = new Dictionary<string, BotStatus>(); var result = new Dictionary<string, BotStatus>();
@@ -79,6 +79,9 @@ public class LoadBackupBotCommandHandler : IRequestHandler<LoadBackupBotCommand,
} }
} }
_logger.LogInformation("Bot loading completed");
_logger.LogInformation($"Bots: {result.Select(b => $"{b.Key} - {b.Value}")}");
return Task.FromResult(botStatus.ToString()); return Task.FromResult(botStatus.ToString());
} }
} }

View File

@@ -41,8 +41,6 @@ namespace Managing.Application.ManageBot
return Task.FromResult(fBot.GetStatus()); return Task.FromResult(fBot.GetStatus());
} }
;
return Task.FromResult(botStatus.ToString()); return Task.FromResult(botStatus.ToString());
} }
} }

View File

@@ -207,7 +207,7 @@ public class TradingService : ITradingService
} }
return _cacheService.GetOrSave($"Fee-{account.Exchange}", return _cacheService.GetOrSave($"Fee-{account.Exchange}",
() => { return _tradingRepository.GetFee(TradingExchanges.Evm)?.Cost ?? 0m; }, TimeSpan.FromHours(2)); () => { return (decimal)_tradingRepository.GetFee(TradingExchanges.Evm)?.Cost; }, TimeSpan.FromHours(2));
} }
public void UpdatePosition(Position position) public void UpdatePosition(Position position)

View File

@@ -17,7 +17,7 @@ public static class ScenarioHelpers
strategy.Period.Value), strategy.Period.Value),
StrategyType.RsiDivergenceConfirm => new RSIDivergenceConfirmStrategy(strategy.Name, strategy.Timeframe, StrategyType.RsiDivergenceConfirm => new RSIDivergenceConfirmStrategy(strategy.Name, strategy.Timeframe,
strategy.Period.Value), strategy.Period.Value),
StrategyType.MacdCross => new MACDCrossStrategy(strategy.Name, strategy.Timeframe, StrategyType.MacdCross => new MacdCrossStrategy(strategy.Name, strategy.Timeframe,
strategy.FastPeriods.Value, strategy.SlowPeriods.Value, strategy.SignalPeriods.Value), strategy.FastPeriods.Value, strategy.SlowPeriods.Value, strategy.SignalPeriods.Value),
StrategyType.EmaCross => new EmaCrossStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value), StrategyType.EmaCross => new EmaCrossStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value),
StrategyType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersStrategy(strategy.Name, strategy.Timeframe, StrategyType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersStrategy(strategy.Name, strategy.Timeframe,

View File

@@ -46,8 +46,8 @@ public static class TradingBox
Signal signal = null; Signal signal = null;
if (strategies.Count > 1) if (strategies.Count > 1)
{ {
var trendSignal = signalOnCandles.Where(s => s.SignalType == SignalType.Trend); var trendSignal = signalOnCandles.Where(s => s.SignalType == SignalType.Trend).ToList();
var signals = signalOnCandles.Where(s => s.SignalType == SignalType.Signal); var signals = signalOnCandles.Where(s => s.SignalType == SignalType.Signal).ToList();
var contextStrategiesCount = strategies.Count(s => s.SignalType == SignalType.Context); var contextStrategiesCount = strategies.Count(s => s.SignalType == SignalType.Context);
var validContext = true; var validContext = true;
@@ -111,7 +111,7 @@ public static class TradingBox
{ {
var position = positions[i]; var position = positions[i];
var nextPosition = i + 1 < positions.Count ? positions[i + 1] : null; var nextPosition = i + 1 < positions.Count ? positions[i + 1] : null;
var (stopLoss, takeProfit) = GetBestSLTPForPosition(candles, position, nextPosition); var (stopLoss, takeProfit) = GetBestSltpForPosition(candles, position, nextPosition);
stoplossPercentage.Add(stopLoss); stoplossPercentage.Add(stopLoss);
takeProfitsPercentage.Add(takeProfit); takeProfitsPercentage.Add(takeProfit);
@@ -126,13 +126,14 @@ public static class TradingBox
return moneyManagement; return moneyManagement;
} }
public static (decimal Stoploss, decimal TakeProfit) GetBestSLTPForPosition(List<Candle> candles, Position position, public static (decimal Stoploss, decimal TakeProfit) GetBestSltpForPosition(List<Candle> candles, Position position,
Position nextPosition) Position nextPosition)
{ {
var stopLoss = 0M; var stopLoss = 0M;
var takeProfit = 0M; var takeProfit = 0M;
var candlesBeforeNextPosition = candles.Where(c => var candlesBeforeNextPosition = candles.Where(c =>
c.Date >= position.Date && c.Date <= (nextPosition == null ? candles.Last().Date : nextPosition.Date)); c.Date >= position.Date && c.Date <= (nextPosition == null ? candles.Last().Date : nextPosition.Date))
.ToList();
if (position.OriginDirection == TradeDirection.Long) if (position.OriginDirection == TradeDirection.Long)
{ {

View File

@@ -21,7 +21,7 @@ public static class TradingHelpers
public static PerformanceMetrics GetStatistics(Dictionary<DateTime, decimal> pnls) public static PerformanceMetrics GetStatistics(Dictionary<DateTime, decimal> pnls)
{ {
var priceSeries = new TimePriceSeries(pnls); var priceSeries = new TimePriceSeries(pnls.DistinctBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value));
return priceSeries.CalculatePerformanceMetrics(); return priceSeries.CalculatePerformanceMetrics();
} }

View File

@@ -6,11 +6,12 @@ using static Managing.Common.Enums;
namespace Managing.Domain.Strategies; namespace Managing.Domain.Strategies;
public class MACDCrossStrategy : Strategy public class MacdCrossStrategy : Strategy
{ {
public List<Signal> Signals { get; set; } public List<Signal> Signals { get; set; }
public MACDCrossStrategy(string name, Timeframe timeframe, int fastPeriods, int slowPeriods, int signalPeriods) : base(name, timeframe, StrategyType.MacdCross) public MacdCrossStrategy(string name, Timeframe timeframe, int fastPeriods, int slowPeriods, int signalPeriods) :
base(name, timeframe, StrategyType.MacdCross)
{ {
Signals = new List<Signal>(); Signals = new List<Signal>();
FastPeriods = fastPeriods; FastPeriods = fastPeriods;
@@ -20,7 +21,7 @@ public class MACDCrossStrategy : Strategy
public override List<Signal> Run() public override List<Signal> Run()
{ {
if (Candles.Count <= 2*(SlowPeriods + SignalPeriods)) if (Candles.Count <= 2 * (SlowPeriods + SignalPeriods))
{ {
return null; return null;
} }
@@ -72,19 +73,20 @@ public class MACDCrossStrategy : Strategy
Date = candle.Date, Date = candle.Date,
Ticker = candle.Ticker, Ticker = candle.Ticker,
Exchange = candle.Exchange, Exchange = candle.Exchange,
FastEma = currentMacd.FastEma.Value,
SlowEma = currentMacd.SlowEma.Value,
Macd = currentMacd.Macd.Value, Macd = currentMacd.Macd.Value,
Histogram = currentMacd.Histogram.Value Histogram = currentMacd.Histogram.Value
}); });
} }
} }
return macdList; return macdList;
} }
private void AddSignal(CandleMacd candleSignal, Timeframe timeframe, TradeDirection direction, Confidence confidence) private void AddSignal(CandleMacd candleSignal, Timeframe timeframe, TradeDirection direction,
Confidence confidence)
{ {
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence, candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType); var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
candleSignal, candleSignal.Date, candleSignal.Exchange, timeframe, Type, SignalType);
if (!Signals.Any(s => s.Identifier == signal.Identifier)) if (!Signals.Any(s => s.Identifier == signal.Identifier))
{ {
Signals.AddItem(signal); Signals.AddItem(signal);
@@ -96,7 +98,5 @@ public class MACDCrossStrategy : Strategy
public double Macd { get; set; } public double Macd { get; set; }
public double Signal { get; set; } public double Signal { get; set; }
public double Histogram { get; set; } public double Histogram { get; set; }
public double FastEma { get; set; }
public double SlowEma { get; set; }
} }
} }

View File

@@ -13,10 +13,10 @@ public static class PriceHelpers
{ {
Exchange = candle.Exchange.ToString(), Exchange = candle.Exchange.ToString(),
Ticker = candle.Ticker, Ticker = candle.Ticker,
OpenTime = candle.OpenTime.ToUniversalTime(), OpenTime = candle.OpenTime,
Open = candle.Open, Open = candle.Open,
Close = candle.Close, Close = candle.Close,
CloseTime = candle.Date.ToUniversalTime(), CloseTime = candle.Date,
High = candle.High, High = candle.High,
Low = candle.Low, Low = candle.Low,
BaseVolume = candle.BaseVolume, BaseVolume = candle.BaseVolume,
@@ -50,9 +50,4 @@ public static class PriceHelpers
Timeframe = MiscExtensions.ParseEnum<Timeframe>(dto.Timeframe) Timeframe = MiscExtensions.ParseEnum<Timeframe>(dto.Timeframe)
}; };
} }
internal static IEnumerable<PriceDto> Map(IEnumerable<Candle> candles)
{
return candles.Select(candle => Map(candle));
}
} }

View File

@@ -227,7 +227,6 @@ namespace Managing.Infrastructure.Messengers.Discord
await OpenPosition(component, trade.AccountName, trade.MoneyManagementName, PositionInitiator.CopyTrading, await OpenPosition(component, trade.AccountName, trade.MoneyManagementName, PositionInitiator.CopyTrading,
trade.Ticker, trade.Direction, Timeframe.FifteenMinutes, trade.Ticker, trade.Direction, Timeframe.FifteenMinutes,
DateTime.Now.AddMinutes(trade.ExpirationMinute), true, trade.Leverage); DateTime.Now.AddMinutes(trade.ExpirationMinute), true, trade.Leverage);
;
} }
public async Task OpenPosition(SocketMessageComponent component, string[] parameters) public async Task OpenPosition(SocketMessageComponent component, string[] parameters)

View File

@@ -40,7 +40,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Theory] [Theory]
[InlineData("")] [InlineData("")]
public async void Should_get_address_balance(string address) public async Task Should_get_address_balance(string address)
{ {
var balance = await _manager.GetAddressBalance(address); var balance = await _manager.GetAddressBalance(address);
Assert.IsType<decimal>(balance); Assert.IsType<decimal>(balance);
@@ -51,7 +51,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Theory] [Theory]
[InlineData("0x17f4BAa9D35Ee54fFbCb2608e20786473c7aa49f")] [InlineData("0x17f4BAa9D35Ee54fFbCb2608e20786473c7aa49f")]
public async void Should_return_holder_list_for_nft_collection(string contract) public async Task Should_return_holder_list_for_nft_collection(string contract)
{ {
var holders = await _manager.GetContractHolders(contract, DateTime.UtcNow.AddDays(-30)); var holders = await _manager.GetContractHolders(contract, DateTime.UtcNow.AddDays(-30));
Assert.IsType<List<Holder>>(holders); Assert.IsType<List<Holder>>(holders);
@@ -61,7 +61,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Theory] [Theory]
[InlineData("0xa435530d50d7D17Fd9fc6E1c897Dbf7C08E12d35", "0x17f4BAa9D35Ee54fFbCb2608e20786473c7aa49f")] [InlineData("0xa435530d50d7D17Fd9fc6E1c897Dbf7C08E12d35", "0x17f4BAa9D35Ee54fFbCb2608e20786473c7aa49f")]
public async void Should_return_event_transfer_nft(string owner, string contract) public async Task Should_return_event_transfer_nft(string owner, string contract)
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var holders = await manager.GetNftEvent(owner, contract); var holders = await manager.GetNftEvent(owner, contract);
@@ -72,7 +72,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Fact] [Fact]
public async void Should_return_date_of_block() public async Task Should_return_date_of_block()
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var date = await manager.GetBlockDate(38793245); var date = await manager.GetBlockDate(38793245);
@@ -121,7 +121,7 @@ public class EvmManagerTests
[Theory] [Theory]
[InlineData("0x0425dEAb364E9121F7CA284129dA854FD5cF22eD", Constants.Chains.Arbitrum)] [InlineData("0x0425dEAb364E9121F7CA284129dA854FD5cF22eD", Constants.Chains.Arbitrum)]
// [InlineData("0x7002AE0Bae7fC67416230F025A32EfE086C0934E", Constants.Chains.Arbitrum)] // [InlineData("0x7002AE0Bae7fC67416230F025A32EfE086C0934E", Constants.Chains.Arbitrum)]
public async void Should_return_balances(string publicAddress, string chainName) public async Task Should_return_balances(string publicAddress, string chainName)
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var chain = _chains.First(c => c.Name == chainName); var chain = _chains.First(c => c.Name == chainName);
@@ -135,7 +135,7 @@ public class EvmManagerTests
[Theory] [Theory]
//[InlineData("0x7002ae0bae7fc67416230f025a32efe086c0934e", Constants.Chains.Arbitrum)] //[InlineData("0x7002ae0bae7fc67416230f025a32efe086c0934e", Constants.Chains.Arbitrum)]
[InlineData("0xc62F5499789b716Aa94a421A60c76c8c13A31ab6", Constants.Chains.Ethereum)] [InlineData("0xc62F5499789b716Aa94a421A60c76c8c13A31ab6", Constants.Chains.Ethereum)]
public async void Should_return_all_balance(string publicAddress, string chainName) public async Task Should_return_all_balance(string publicAddress, string chainName)
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var chain = _chains.First(c => c.Name == chainName); var chain = _chains.First(c => c.Name == chainName);
@@ -160,7 +160,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Theory] [Theory]
[InlineData("")] [InlineData("")]
public async void Should_return_balance_of_ethers(string publicAddress) public async Task Should_return_balance_of_ethers(string publicAddress)
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var chain = _chains.First(c => c.Name == Constants.Chains.Ethereum); var chain = _chains.First(c => c.Name == Constants.Chains.Ethereum);
@@ -172,7 +172,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Theory] [Theory]
[InlineData("")] [InlineData("")]
public async void Should_return_all_balance_for_all_chain(string publicAddress) public async Task Should_return_all_balance_for_all_chain(string publicAddress)
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var balances = await manager.GetAllBalancesOnAllChain(publicAddress); var balances = await manager.GetAllBalancesOnAllChain(publicAddress);
@@ -184,12 +184,12 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Theory] [Theory]
[InlineData(Ticker.BTC, Timeframe.FiveMinutes)] [InlineData(Ticker.BTC, Timeframe.FiveMinutes)]
public async void Get_Prices(Ticker ticker, Timeframe timeframe) public async Task Get_Prices(Ticker ticker, Timeframe timeframe)
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var candles = await manager.GetCandles(SubgraphProvider.ChainlinkPrice, ticker, DateTime.UtcNow, timeframe); var candles = await manager.GetCandles(SubgraphProvider.ChainlinkPrice, ticker, DateTime.UtcNow, timeframe);
if (candles == null || !candles.Any()) if (!candles.Any())
{ {
candles = await manager.GetCandles(SubgraphProvider.ChainlinkGmx, ticker, DateTime.UtcNow, timeframe); candles = await manager.GetCandles(SubgraphProvider.ChainlinkGmx, ticker, DateTime.UtcNow, timeframe);
} }
@@ -200,7 +200,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Fact] [Fact]
public async void Get_Available_Tickers() public async Task Get_Available_Tickers()
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var tickers = await manager.GetAvailableTicker(); var tickers = await manager.GetAvailableTicker();
@@ -210,7 +210,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Fact] [Fact]
public async void GetLastCandle() public async Task GetLastCandle()
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var candle = await manager.GetCandle(SubgraphProvider.Gbc, Ticker.BTC); var candle = await manager.GetCandle(SubgraphProvider.Gbc, Ticker.BTC);
@@ -220,7 +220,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Fact] [Fact]
public async void Should_Init_Address_For_Trading() public async Task Should_Init_Address_For_Trading()
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var accountInitilized = await manager.InitAddress(Constants.Chains.Arbitrum, PublicAddress, "PrivateKey"); var accountInitilized = await manager.InitAddress(Constants.Chains.Arbitrum, PublicAddress, "PrivateKey");
@@ -230,7 +230,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Fact] [Fact]
public async void Should_send_eth_from_account() public async Task Should_send_eth_from_account()
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var chain = _chains.First(c => c.Name == Constants.Chains.Arbitrum); var chain = _chains.First(c => c.Name == Constants.Chains.Arbitrum);
@@ -250,7 +250,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Fact] [Fact]
public async void Should_send_Gmx_from_account() public async Task Should_send_Gmx_from_account()
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var chain = _chains.First(c => c.Name == Constants.Chains.Arbitrum); var chain = _chains.First(c => c.Name == Constants.Chains.Arbitrum);
@@ -270,7 +270,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Fact] [Fact]
public async void Should_return_allowance() public async Task Should_return_allowance()
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var account = PrivateKeys.GetAccount(); var account = PrivateKeys.GetAccount();
@@ -281,7 +281,7 @@ public class EvmManagerTests
[Ignore] [Ignore]
[Fact] [Fact]
public async void Should_set_allowance() public async Task Should_set_allowance()
{ {
var manager = new EvmManager(Subgraphs); var manager = new EvmManager(Subgraphs);
var account = PrivateKeys.GetAccount(); var account = PrivateKeys.GetAccount();
@@ -294,7 +294,7 @@ public class EvmManagerTests
} }
[Fact] [Fact]
public async void Should_return_GmxGasPrice() public async Task Should_return_GmxGasPrice()
{ {
var result = var result =
await EvmBase.GetGasPrice(new Web3(_chains.First(c => c.Name == Constants.Chains.Arbitrum).RpcUrl)); await EvmBase.GetGasPrice(new Web3(_chains.First(c => c.Name == Constants.Chains.Arbitrum).RpcUrl));

View File

@@ -10,7 +10,6 @@ using Managing.Domain.Statistics;
using Managing.Domain.Trades; using Managing.Domain.Trades;
using Managing.Infrastructure.Evm.Abstractions; using Managing.Infrastructure.Evm.Abstractions;
using Managing.Infrastructure.Evm.Models; using Managing.Infrastructure.Evm.Models;
using Managing.Infrastructure.Evm.Models.Gmx.v1;
using Managing.Infrastructure.Evm.Models.Gmx.v2; using Managing.Infrastructure.Evm.Models.Gmx.v2;
using Managing.Infrastructure.Evm.Referentials; using Managing.Infrastructure.Evm.Referentials;
using Managing.Infrastructure.Evm.Services; using Managing.Infrastructure.Evm.Services;
@@ -318,7 +317,7 @@ public class EvmManager : IEvmManager
var geckoToken = geckoTokens.FirstOrDefault(x => var geckoToken = geckoTokens.FirstOrDefault(x =>
string.Equals(x.Symbol, tokens[i].Symbol, StringComparison.InvariantCultureIgnoreCase)); string.Equals(x.Symbol, tokens[i].Symbol, StringComparison.InvariantCultureIgnoreCase));
evmTokens.Add((tokenBalance, geckoToken)); evmTokens.Add((tokenBalance, geckoToken)!);
} }
} }
@@ -379,14 +378,16 @@ public class EvmManager : IEvmManager
if (gmxPrices == null) if (gmxPrices == null)
return null; return null;
gmxPrices.Candles = gmxPrices.Candles.Where(p => p[0] >= startDate.ToUnixTimestamp()).ToList(); var filteredCandles = gmxPrices.Candles.Where(p => p[0] >= startDate.ToUnixTimestamp()).ToList();
gmxPrices.Candles.RemoveAt(gmxPrices.Candles.Count - 1);
var candles = new List<Candle>(); var candles = new List<Candle>();
var timeBetweenCandles = gmxPrices.Candles[0][0] - gmxPrices.Candles[1][0];
for (int i = 0; i < gmxPrices.Candles.Count; i++) var timeBetweenCandles =
gmxPrices.Candles.Count > 2 ? gmxPrices.Candles[0][0] - gmxPrices.Candles[1][0] : 900; // Default 15 minutes
for (int i = 0; i < filteredCandles.Count; i++)
{ {
var c = GmxV2Mappers.Map(gmxPrices.Candles[i], ticker, timeframe, (int)timeBetweenCandles); var c = GmxV2Mappers.Map(filteredCandles[i], ticker, timeframe, (int)timeBetweenCandles);
candles.Add(c); candles.Add(c);
} }

View File

@@ -110,7 +110,7 @@ internal static class GmxV2Mappers
{ {
return new Candle() return new Candle()
{ {
Date = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0]).AddSeconds(timeBetween).AddSeconds(-1), Date = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0] + timeBetween).AddSeconds(-1),
OpenTime = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0]), OpenTime = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0]),
Open = Convert.ToDecimal(marketPrices[1]), Open = Convert.ToDecimal(marketPrices[1]),
High = Convert.ToDecimal(marketPrices[2]), High = Convert.ToDecimal(marketPrices[2]),

View File

@@ -0,0 +1,18 @@
import { create } from 'zustand'
import type { MoneyManagement } from '../../generated/ManagingApi'
type CustomMoneyManagementStore = {
setCustomMoneyManagement: (custom: MoneyManagement) => void
moneyManagement: MoneyManagement | null
}
export const useCustomMoneyManagement = create<CustomMoneyManagementStore>((set) => ({
moneyManagement: null,
setCustomMoneyManagement: (custom) => {
set((state) => ({
...state,
moneyManagement: custom,
}))
},
}))

View File

@@ -22,8 +22,6 @@ const LogIn = () => {
const message = 'wagmi' const message = 'wagmi'
const signature = await signMessageAsync({ message }) const signature = await signMessageAsync({ message })
const t = new Toast('Creating token') const t = new Toast('Creating token')
console.log(t)
if (signature && address) { if (signature && address) {
const userClient = new UserClient({}, apiUrl) const userClient = new UserClient({}, apiUrl)
@@ -37,10 +35,9 @@ const LogIn = () => {
}) })
.then((data) => { .then((data) => {
setCookie('token', data, 1) setCookie('token', data, 1)
console.log('token', data)
setTimeout(() => { setTimeout(() => {
location.assign("/"); location.assign("/");
}, 2000); }, 1000);
}) })
.catch((err: any) => { .catch((err: any) => {
t.update('error', 'Error : Some thing bad happen') t.update('error', 'Error : Some thing bad happen')

View File

@@ -38,7 +38,7 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
showLoopSlider ? 3 : 1 showLoopSlider ? 3 : 1
) )
const [balance, setBalance] = React.useState<number>(10000) const [balance, setBalance] = React.useState<number>(10000)
const [days, setDays] = React.useState<number>(-10) const [days, setDays] = React.useState<number>(-17)
const [customMoneyManagement, setCustomMoneyManagement] = const [customMoneyManagement, setCustomMoneyManagement] =
React.useState<MoneyManagement>() React.useState<MoneyManagement>()
@@ -58,6 +58,7 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
const { register, handleSubmit } = useForm<IBacktestsFormInput>() const { register, handleSubmit } = useForm<IBacktestsFormInput>()
const onSubmit: SubmitHandler<IBacktestsFormInput> = async (form) => { const onSubmit: SubmitHandler<IBacktestsFormInput> = async (form) => {
const { scenarioName, tickers } = form const { scenarioName, tickers } = form
console.log(customMoneyManagement)
closeModal() closeModal()
for (let sIndex = 0; sIndex < scenarioName.length; sIndex++) { for (let sIndex = 0; sIndex < scenarioName.length; sIndex++) {
for (let tIndex = 0; tIndex < tickers.length; tIndex++) { for (let tIndex = 0; tIndex < tickers.length; tIndex++) {
@@ -76,7 +77,7 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
form: IBacktestsFormInput, form: IBacktestsFormInput,
ticker: string, ticker: string,
scenarioName: string, scenarioName: string,
moneyManagement: MoneyManagement | undefined, customMoneyManagement: MoneyManagement | undefined,
loopCount: number loopCount: number
) { ) {
const t = new Toast(ticker + ' is running') const t = new Toast(ticker + ' is running')
@@ -92,7 +93,7 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
balance, balance,
selectedMoneyManagement, selectedMoneyManagement,
form.save, form.save,
selectedMoneyManagement ? undefined : moneyManagement showCustomMoneyManagement ? customMoneyManagement : undefined
) )
.then((backtest: Backtest) => { .then((backtest: Backtest) => {
t.update('success', `${backtest.ticker} Backtest Succeeded`) t.update('success', `${backtest.ticker} Backtest Succeeded`)
@@ -125,8 +126,7 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
} }
function onMoneyManagementChange(e: any) { function onMoneyManagementChange(e: any) {
console.log(e.target.value) if (e.target.value == 'custom') {
if (e.target.value == 'Custom') {
setShowCustomMoneyManagement(true) setShowCustomMoneyManagement(true)
} else { } else {
setShowCustomMoneyManagement(false) setShowCustomMoneyManagement(false)
@@ -210,6 +210,24 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
))} ))}
</select> </select>
</FormInput> </FormInput>
<FormInput label="Timeframe" htmlFor="timeframe">
<select
className="select w-full max-w-xs"
{...register('timeframe', {
onChange(event) {
setSelectedTimeframeEvent(event)
},
})}
>
{Object.keys(Timeframe).map((item) => (
<option key={item} value={item}>
{item}
</option>
))}
</select>
</FormInput>
<FormInput label="Money Management" htmlFor="moneyManagement"> <FormInput label="Money Management" htmlFor="moneyManagement">
<select <select
className="select w-full max-w-xs" className="select w-full max-w-xs"
@@ -224,35 +242,21 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
{item.name} {item.name}
</option> </option>
))} ))}
<option key="custom" value="custom">
Custom
</option>
</select> </select>
</FormInput> </FormInput>
<CustomMoneyManagement <CustomMoneyManagement
onCreateMoneyManagement={setCustomMoneyManagement} onCreateMoneyManagement={setCustomMoneyManagement}
timeframe={selectedTimeframe || Timeframe.FiveMinutes} timeframe={selectedTimeframe || Timeframe.FifteenMinutes}
showCustomMoneyManagement={showCustomMoneyManagement} showCustomMoneyManagement={showCustomMoneyManagement}
></CustomMoneyManagement> ></CustomMoneyManagement>
<FormInput label="Type" htmlFor="botType"> <FormInput label="Type" htmlFor="botType">
<select className="select w-full max-w-xs" {...register('botType')}> <select className="select w-full max-w-xs" {...register('botType')}>
{Object.keys(BotType).map((item) => ( {[BotType.ScalpingBot, BotType.FlippingBot].map((item) => (
<option key={item} value={item}>
{item}
</option>
))}
</select>
</FormInput>
<FormInput label="Timeframe" htmlFor="timeframe">
<select
className="select w-full max-w-xs"
{...register('timeframe', {
onChange(event) {
setSelectedTimeframeEvent(event)
},
})}
>
{Object.keys(Timeframe).map((item) => (
<option key={item} value={item}> <option key={item} value={item}>
{item} {item}
</option> </option>

View File

@@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react'
import type { MoneyManagement, Timeframe } from '../../../generated/ManagingApi' import type { MoneyManagement, Timeframe } from '../../../generated/ManagingApi'
import { Slider } from '../../atoms' import { Slider } from '../../atoms'
import FormInput from '../../mollecules/FormInput/FormInput' import FormInput from '../../mollecules/FormInput/FormInput'
import { useCustomMoneyManagement } from '../../../app/store/customMoneyManagement'
type ICustomMoneyManagement = { type ICustomMoneyManagement = {
onCreateMoneyManagement: (moneyManagement: MoneyManagement) => void onCreateMoneyManagement: (moneyManagement: MoneyManagement) => void
@@ -15,10 +16,12 @@ const CustomMoneyManagement: React.FC<ICustomMoneyManagement> = ({
timeframe, timeframe,
showCustomMoneyManagement, showCustomMoneyManagement,
}) => { }) => {
const [balanceAtRisk, setBalanceAtRisk] = useState<number>(1) const { moneyManagement, setCustomMoneyManagement } = useCustomMoneyManagement()
const [leverage, setLeverage] = useState<number>(1)
const [takeProfit, setTakeProfit] = useState<number>(1) const [balanceAtRisk, setBalanceAtRisk] = useState<number>(moneyManagement?.balanceAtRisk || 5)
const [stopLoss, setStopLoss] = useState<number>(1) const [leverage, setLeverage] = useState<number>(moneyManagement?.leverage || 1)
const [takeProfit, setTakeProfit] = useState<number>(moneyManagement?.takeProfit || 2)
const [stopLoss, setStopLoss] = useState<number>(moneyManagement?.stopLoss || 1)
const handleCreateMoneyManagement = () => { const handleCreateMoneyManagement = () => {
const moneyManagement: MoneyManagement = { const moneyManagement: MoneyManagement = {
@@ -30,6 +33,7 @@ const CustomMoneyManagement: React.FC<ICustomMoneyManagement> = ({
timeframe, timeframe,
} }
onCreateMoneyManagement(moneyManagement) onCreateMoneyManagement(moneyManagement)
setCustomMoneyManagement(moneyManagement)
} }
useEffect(() => { useEffect(() => {
@@ -48,51 +52,55 @@ const CustomMoneyManagement: React.FC<ICustomMoneyManagement> = ({
<FormInput <FormInput
label="Balance at risk" label="Balance at risk"
htmlFor="balanceAtRisk" htmlFor="balanceAtRisk"
inline={true} inline={false}
> >
<Slider <input
id="balanceAtRisk" id="balanceAtRisk"
value={balanceAtRisk} value={balanceAtRisk}
onChange={(e) => setBalanceAtRisk(parseInt(e.target.value))} onChange={(e) => setBalanceAtRisk(parseInt(e.target.value))}
min="1" min="1"
max="100" max="100"
step="1" step="1"
suffixValue=" %" type='number'
></Slider> className='input input-bordered'
></input>
</FormInput> </FormInput>
<FormInput label="Leverage" htmlFor="leverage" inline={true}> <FormInput label="Leverage" htmlFor="leverage" inline={false}>
<Slider <input
id="leverage" id="leverage"
value={leverage} value={leverage}
max="50" max="50"
min="1" min="1"
step="1" step="1"
onChange={(e: any) => setLeverage(e.target.value)} onChange={(e: any) => setLeverage(e.target.value)}
prefixValue="x " type='number'
></Slider> className='input input-bordered'
></input>
</FormInput> </FormInput>
<FormInput label="TP %" htmlFor="takeProfit" inline={true}> <FormInput label="TP %" htmlFor="takeProfit" inline={false}>
<Slider <input
id="takeProfit" id="takeProfit"
value={takeProfit} value={takeProfit}
onChange={(e: any) => setTakeProfit(e.target.value)} onChange={(e: any) => setTakeProfit(e.target.value)}
step="0.01" step="0.01"
max="20" max="20"
suffixValue=" %" type='number'
></Slider> className='input input-bordered'
></input>
</FormInput> </FormInput>
<FormInput label="SL %" htmlFor="stopLoss" inline={true}> <FormInput label="SL %" htmlFor="stopLoss" inline={false}>
<Slider <input
id="stopLoss" id="stopLoss"
value={stopLoss} value={stopLoss}
onChange={(e: any) => setStopLoss(e.target.value)} onChange={(e: any) => setStopLoss(e.target.value)}
step="0.01" step="0.01"
max="20" max="20"
suffixValue=" %" type='number'
></Slider> className='input input-bordered'
></input>
</FormInput> </FormInput>
</div> </div>
</div> </div>

View File

@@ -16,11 +16,7 @@ export default class AuthorizedApiBase {
transformOptions = (options: any): Promise<RequestInit> => { transformOptions = (options: any): Promise<RequestInit> => {
const cookies = new Cookies() const cookies = new Cookies()
// Retrieve the bearer token from the cookies
const bearerToken = cookies.get('token') const bearerToken = cookies.get('token')
// eslint-disable-next-line no-console
console.log(bearerToken)
if (bearerToken) { if (bearerToken) {
options.headers.Authorization = `Bearer ${bearerToken}` options.headers.Authorization = `Bearer ${bearerToken}`
} }