GMX v2 - Trading (#7)
* Move PrivateKeys.cs * Update gitignore * Update gitignore * updt * Extract GmxServiceTests.cs * Refact * update todo * Update code * Fix hashdata * Replace static token hashed datas * Set allowance * Add get orders * Add get orders tests * Add ignore * add close orders * revert * Add get gas limit * Start increasePosition. Todo: Finish GetExecutionFee and estimateGas * little refact * Update gitignore * Fix namespaces and clean repo * Add tests samples * Add execution fee * Add increase position * Handle backtest on the frontend * Add tests * Update increase * Test increase * fix increase * Fix size * Start get position * Update get positions * Fix get position * Update rpc and trade mappers * Finish close position * Fix leverage
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Repositories;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Backtesting;
|
||||
using Managing.Application.Bots.Base;
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using Managing.Domain.Scenarios;
|
||||
using Moq;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
@@ -22,7 +26,7 @@ namespace Managing.Application.Tests
|
||||
private readonly string _s = "|";
|
||||
private List<double> _elapsedTimes { get; set; }
|
||||
|
||||
public BotsTests() : base ()
|
||||
public BotsTests() : base()
|
||||
{
|
||||
var backtestRepository = new Mock<IBacktestRepository>().Object;
|
||||
var discordService = new Mock<IMessengerService>().Object;
|
||||
@@ -41,17 +45,24 @@ namespace Managing.Application.Tests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Ticker.BTC, Timeframe.OneDay, -100)]
|
||||
public void SwingBot_Should_Return_Positiv_Profit_For_Every_Position(Ticker ticker, Timeframe timeframe, int days)
|
||||
[InlineData(Ticker.BTC, Timeframe.FifteenMinutes, -10)]
|
||||
public void SwingBot_Should_Return_Positiv_Profit_For_Every_Position(Ticker ticker, Timeframe timeframe,
|
||||
int days)
|
||||
{
|
||||
// Arrange
|
||||
var scenario = new Scenario("ScalpingScenario");
|
||||
var scenario = new Scenario("FlippingScenario");
|
||||
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.RsiDivergence, timeframe, "RsiDiv", period: 14);
|
||||
scenario.AddStrategy(strategy);
|
||||
var localCandles =
|
||||
FileHelpers.ReadJson<List<Candle>>($"{ticker.ToString()}-{timeframe.ToString()}-candles.json");
|
||||
|
||||
// Act
|
||||
var backtestResult = _backtester.RunFlippingBotBacktest(Account, MoneyManagement, ticker, scenario, timeframe, Convert.ToDouble(days*2), 1000);
|
||||
WriteCsvReport(backtestResult.GetStringReport());
|
||||
var backtestResult = _backtester.RunFlippingBotBacktest(_account, MoneyManagement, ticker, scenario,
|
||||
timeframe, Convert.ToDouble(days), 1000, initialCandles: localCandles.TakeLast(500).ToList());
|
||||
|
||||
var json = JsonConvert.SerializeObject(backtestResult, Formatting.None);
|
||||
File.WriteAllText($"{ticker.ToString()}-{timeframe.ToString()}-{Guid.NewGuid()}.json", json);
|
||||
// WriteCsvReport(backtestResult.GetStringReport());
|
||||
|
||||
// Assert
|
||||
Assert.True(backtestResult.FinalPnl > 0);
|
||||
@@ -67,7 +78,8 @@ namespace Managing.Application.Tests
|
||||
//[InlineData(Enums.Exchanges.Binance, "BTCUSDT", Timeframe.ThirtyMinutes, -4)]
|
||||
//[InlineData(Enums.Exchanges.Binance, "BTCUSDT", Timeframe.FifteenMinutes, -4)]
|
||||
[InlineData(Ticker.BTC, Timeframe.FifteenMinutes, -14)]
|
||||
public void ScalpingBot_Should_Return_Positiv_Profit_For_Every_Position(Ticker ticker, Timeframe timeframe, int days)
|
||||
public void ScalpingBot_Should_Return_Positiv_Profit_For_Every_Position(Ticker ticker, Timeframe timeframe,
|
||||
int days)
|
||||
{
|
||||
// Arrange
|
||||
var scenario = new Scenario("ScalpingScenario");
|
||||
@@ -75,7 +87,8 @@ namespace Managing.Application.Tests
|
||||
scenario.AddStrategy(strategy);
|
||||
|
||||
// Act
|
||||
var backtestResult = _backtester.RunScalpingBotBacktest(Account, MoneyManagement, ticker, scenario, timeframe, Convert.ToDouble(days), 1000);
|
||||
var backtestResult = _backtester.RunScalpingBotBacktest(_account, MoneyManagement, ticker, scenario,
|
||||
timeframe, Convert.ToDouble(days), 1000);
|
||||
//WriteCsvReport(backtestResult.GetStringReport());
|
||||
|
||||
// Assert
|
||||
@@ -86,11 +99,13 @@ namespace Managing.Application.Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData(Ticker.BTC, Timeframe.FifteenMinutes, -8)]
|
||||
public void MacdCross_Should_Return_Positiv_Profit_For_Every_Position(Ticker ticker, Timeframe timeframe, int days)
|
||||
public void MacdCross_Should_Return_Positiv_Profit_For_Every_Position(Ticker ticker, Timeframe timeframe,
|
||||
int days)
|
||||
{
|
||||
// Arrange
|
||||
var scenario = new Scenario("ScalpingScenario");
|
||||
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.MacdCross, timeframe, "RsiDiv", fastPeriods: 12, slowPeriods: 26, signalPeriods: 9);
|
||||
var strategy = ScenarioHelpers.BuildStrategy(StrategyType.MacdCross, timeframe, "RsiDiv", fastPeriods: 12,
|
||||
slowPeriods: 26, signalPeriods: 9);
|
||||
scenario.AddStrategy(strategy);
|
||||
|
||||
var moneyManagement = new MoneyManagement()
|
||||
@@ -103,7 +118,8 @@ namespace Managing.Application.Tests
|
||||
};
|
||||
|
||||
// Act
|
||||
var backtestResult = _backtester.RunScalpingBotBacktest(Account, moneyManagement, ticker, scenario, timeframe, Convert.ToDouble(days), 1000);
|
||||
var backtestResult = _backtester.RunScalpingBotBacktest(_account, moneyManagement, ticker, scenario,
|
||||
timeframe, Convert.ToDouble(days), 1000);
|
||||
WriteCsvReport(backtestResult.GetStringReport());
|
||||
|
||||
// Assert
|
||||
@@ -115,7 +131,8 @@ namespace Managing.Application.Tests
|
||||
[Theory]
|
||||
[InlineData(Timeframe.FifteenMinutes, -6, StrategyType.RsiDivergenceConfirm, BotType.ScalpingBot)]
|
||||
//[InlineData(Timeframe.FifteenMinutes, -6, Enums.StrategyType.RsiDivergenceConfirm, Enums.BotType.FlippingBot)]
|
||||
public void GetBestPeriodRsiForDivergenceFlippingBot(Timeframe timeframe, int days, StrategyType strategyType, BotType botType)
|
||||
public void GetBestPeriodRsiForDivergenceFlippingBot(Timeframe timeframe, int days, StrategyType strategyType,
|
||||
BotType botType)
|
||||
{
|
||||
var result = new List<Tuple<string, int, decimal, decimal, decimal, decimal>>();
|
||||
var errors = new List<string>();
|
||||
@@ -124,24 +141,27 @@ namespace Managing.Application.Tests
|
||||
MaxDegreeOfParallelism = 4
|
||||
};
|
||||
|
||||
var periodRange = new List<int>() { 2, 7};
|
||||
var periodRange = new List<int>() { 2, 7 };
|
||||
var stopLossRange = new List<decimal>() { 0.005m, 0.05m, 0.005m };
|
||||
var takeProfitRange = new List<decimal>() { 0.01m, 0.1m, 0.02m };
|
||||
var fileIdentifier = $"{strategyType}-{timeframe}";
|
||||
var completedTest = 0;
|
||||
var totalTests = GetTotalTrades(periodRange, stopLossRange, takeProfitRange) * Enum.GetNames(typeof(Ticker)).Length;
|
||||
var totalTests = GetTotalTrades(periodRange, stopLossRange, takeProfitRange) *
|
||||
Enum.GetNames(typeof(Ticker)).Length;
|
||||
|
||||
CleanAnalyseFile(fileIdentifier);
|
||||
UpdateProgression(totalTests, completedTest);
|
||||
|
||||
Parallel.ForEach((Ticker[])Enum.GetValues(typeof(Ticker)), options, ticker => {
|
||||
|
||||
var candles = _exchangeService.GetCandles(Account, ticker, DateTime.Now.AddDays(Convert.ToDouble(days)), timeframe).Result;
|
||||
Parallel.ForEach((Ticker[])Enum.GetValues(typeof(Ticker)), options, ticker =>
|
||||
{
|
||||
var candles = _exchangeService
|
||||
.GetCandles(_account, ticker, DateTime.Now.AddDays(Convert.ToDouble(days)), timeframe).Result;
|
||||
|
||||
if (candles == null || candles.Count == 0)
|
||||
return;
|
||||
|
||||
Parallel.For(periodRange[0], periodRange[1], options, i => {
|
||||
Parallel.For(periodRange[0], periodRange[1], options, i =>
|
||||
{
|
||||
var scenario = new Scenario("ScalpingScenario");
|
||||
var strategy = ScenarioHelpers.BuildStrategy(strategyType, timeframe, "RsiDiv", period: i);
|
||||
scenario.AddStrategy(strategy);
|
||||
@@ -150,7 +170,7 @@ namespace Managing.Application.Tests
|
||||
for (decimal s = stopLossRange[0]; s < stopLossRange[1]; s += stopLossRange[2])
|
||||
{
|
||||
// +1% to +10% in 1%
|
||||
for(decimal t = takeProfitRange[0]; t < takeProfitRange[1]; t += takeProfitRange[2])
|
||||
for (decimal t = takeProfitRange[0]; t < takeProfitRange[1]; t += takeProfitRange[2])
|
||||
{
|
||||
var moneyManagement = new MoneyManagement()
|
||||
{
|
||||
@@ -165,25 +185,29 @@ namespace Managing.Application.Tests
|
||||
{
|
||||
var timer = new Stopwatch();
|
||||
timer.Start();
|
||||
|
||||
|
||||
var backtestResult = botType switch
|
||||
{
|
||||
BotType.SimpleBot => throw new NotImplementedException(),
|
||||
BotType.ScalpingBot => _backtester.RunScalpingBotBacktest(Account, moneyManagement, scenario, timeframe, candles, 1000),
|
||||
BotType.FlippingBot => _backtester.RunFlippingBotBacktest(Account, moneyManagement, scenario, timeframe, candles, 1000),
|
||||
BotType.ScalpingBot => _backtester.RunScalpingBotBacktest(_account, moneyManagement,
|
||||
scenario, timeframe, candles, 1000),
|
||||
BotType.FlippingBot => _backtester.RunFlippingBotBacktest(_account, moneyManagement,
|
||||
scenario, timeframe, candles, 1000),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
timer.Stop();
|
||||
|
||||
if (backtestResult.FinalPnl > 0
|
||||
&& (backtestResult.GrowthPercentage - backtestResult.HodlPercentage) > 30
|
||||
|
||||
if (backtestResult.FinalPnl > 0
|
||||
&& (backtestResult.GrowthPercentage - backtestResult.HodlPercentage) > 30
|
||||
&& backtestResult.Statistics.MaxDrawdown < 3)
|
||||
{
|
||||
var currentResult = new Tuple<string, int, decimal, decimal, decimal, decimal>(ticker.ToString(), i,
|
||||
backtestResult.FinalPnl, s, t, backtestResult.GrowthPercentage - backtestResult.HodlPercentage);
|
||||
var currentResult = new Tuple<string, int, decimal, decimal, decimal, decimal>(
|
||||
ticker.ToString(), i,
|
||||
backtestResult.FinalPnl, s, t,
|
||||
backtestResult.GrowthPercentage - backtestResult.HodlPercentage);
|
||||
result.Add(currentResult);
|
||||
}
|
||||
|
||||
|
||||
completedTest++;
|
||||
UpdateProgression(totalTests, completedTest, timer.Elapsed.TotalSeconds);
|
||||
}
|
||||
@@ -199,7 +223,8 @@ namespace Managing.Application.Tests
|
||||
|
||||
foreach (var r in result)
|
||||
{
|
||||
WriteCsvAnalyse($"{r.Item1}{_s}{r.Item2}{_s}{r.Item3.ToString("0.000")}{_s}{r.Item4 * 100}{_s}{r.Item5 * 100}{_s}{r.Item6}");
|
||||
WriteCsvAnalyse(
|
||||
$"{r.Item1}{_s}{r.Item2}{_s}{r.Item3.ToString("0.000")}{_s}{r.Item4 * 100}{_s}{r.Item5 * 100}{_s}{r.Item6}");
|
||||
}
|
||||
|
||||
foreach (var e in errors)
|
||||
@@ -208,7 +233,8 @@ namespace Managing.Application.Tests
|
||||
}
|
||||
|
||||
var bestResult = result.OrderByDescending(b => b.Item3).FirstOrDefault();
|
||||
WriteCsvAnalyse($"Best result : {bestResult.Item1} - Rsi Period : {bestResult.Item2} - {bestResult.Item3} - SL : {bestResult.Item4}% - TP : {bestResult.Item5}%");
|
||||
WriteCsvAnalyse(
|
||||
$"Best result : {bestResult.Item1} - Rsi Period : {bestResult.Item2} - {bestResult.Item3} - SL : {bestResult.Item4}% - TP : {bestResult.Item5}%");
|
||||
|
||||
Assert.True(result.Any());
|
||||
}
|
||||
@@ -217,7 +243,8 @@ namespace Managing.Application.Tests
|
||||
[Theory]
|
||||
[InlineData(Timeframe.OneHour, -30, StrategyType.MacdCross, BotType.FlippingBot)]
|
||||
[InlineData(Timeframe.OneHour, -30, StrategyType.MacdCross, BotType.ScalpingBot)]
|
||||
public void GetBestMMForMacdFlippingBot(Timeframe timeframe, int days, StrategyType strategyType, BotType botType)
|
||||
public void GetBestMMForMacdFlippingBot(Timeframe timeframe, int days, StrategyType strategyType,
|
||||
BotType botType)
|
||||
{
|
||||
var result = new List<Tuple<string, decimal, decimal, decimal, decimal>>();
|
||||
var errors = new List<string>();
|
||||
@@ -230,20 +257,23 @@ namespace Managing.Application.Tests
|
||||
var takeProfitRange = new List<decimal>() { 0.01m, 0.1m, 0.02m };
|
||||
var fileIdentifier = $"{strategyType}-{timeframe}-{botType}";
|
||||
var completedTest = 0;
|
||||
var totalTests = GetTotalTradeForStopLossTakeProfit(stopLossRange, takeProfitRange) * Enum.GetNames(typeof(Ticker)).Length;
|
||||
var totalTests = GetTotalTradeForStopLossTakeProfit(stopLossRange, takeProfitRange) *
|
||||
Enum.GetNames(typeof(Ticker)).Length;
|
||||
|
||||
CleanAnalyseFile(fileIdentifier);
|
||||
UpdateProgression(totalTests, completedTest);
|
||||
|
||||
Parallel.ForEach((Ticker[])Enum.GetValues(typeof(Ticker)), options, ticker => {
|
||||
|
||||
var candles = _exchangeService.GetCandles(Account, ticker, DateTime.Now.AddDays(Convert.ToDouble(days)), timeframe).Result;
|
||||
Parallel.ForEach((Ticker[])Enum.GetValues(typeof(Ticker)), options, ticker =>
|
||||
{
|
||||
var candles = _exchangeService
|
||||
.GetCandles(_account, ticker, DateTime.Now.AddDays(Convert.ToDouble(days)), timeframe).Result;
|
||||
|
||||
if (candles == null || candles.Count == 0)
|
||||
return;
|
||||
|
||||
var scenario = new Scenario("ScalpingScenario");
|
||||
var strategy = ScenarioHelpers.BuildStrategy(strategyType, timeframe, "RsiDiv", fastPeriods: 12, slowPeriods: 26, signalPeriods: 9);
|
||||
var strategy = ScenarioHelpers.BuildStrategy(strategyType, timeframe, "RsiDiv", fastPeriods: 12,
|
||||
slowPeriods: 26, signalPeriods: 9);
|
||||
scenario.AddStrategy(strategy);
|
||||
|
||||
// -0.5 to -5
|
||||
@@ -268,8 +298,10 @@ namespace Managing.Application.Tests
|
||||
var backtestResult = botType switch
|
||||
{
|
||||
BotType.SimpleBot => throw new NotImplementedException(),
|
||||
BotType.ScalpingBot => _backtester.RunScalpingBotBacktest(Account, moneyManagement, scenario, timeframe, candles, 1000),
|
||||
BotType.FlippingBot => _backtester.RunFlippingBotBacktest(Account, moneyManagement, scenario, timeframe, candles, 1000),
|
||||
BotType.ScalpingBot => _backtester.RunScalpingBotBacktest(_account, moneyManagement,
|
||||
scenario, timeframe, candles, 1000),
|
||||
BotType.FlippingBot => _backtester.RunFlippingBotBacktest(_account, moneyManagement,
|
||||
scenario, timeframe, candles, 1000),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
@@ -277,8 +309,10 @@ namespace Managing.Application.Tests
|
||||
&& (backtestResult.GrowthPercentage - backtestResult.HodlPercentage) > 30
|
||||
&& backtestResult.Statistics.MaxDrawdown < 3)
|
||||
{
|
||||
var currentResult = new Tuple<string, decimal, decimal, decimal, decimal>(ticker.ToString(),
|
||||
backtestResult.FinalPnl, s, t, backtestResult.GrowthPercentage - backtestResult.HodlPercentage);
|
||||
var currentResult = new Tuple<string, decimal, decimal, decimal, decimal>(
|
||||
ticker.ToString(),
|
||||
backtestResult.FinalPnl, s, t,
|
||||
backtestResult.GrowthPercentage - backtestResult.HodlPercentage);
|
||||
result.Add(currentResult);
|
||||
}
|
||||
|
||||
@@ -290,6 +324,7 @@ namespace Managing.Application.Tests
|
||||
completedTest++;
|
||||
errors.Add($"{ticker}{_s}{s}{_s}{t}{_s}{ex.Message}");
|
||||
}
|
||||
|
||||
timer.Stop();
|
||||
}
|
||||
}
|
||||
@@ -297,7 +332,8 @@ namespace Managing.Application.Tests
|
||||
|
||||
foreach (var r in result)
|
||||
{
|
||||
WriteCsvAnalyse($"{r.Item1}{_s}{r.Item2.ToString("0.000")}{_s}{r.Item3 * 100}{_s}{r.Item4 * 100}{_s}{r.Item5}");
|
||||
WriteCsvAnalyse(
|
||||
$"{r.Item1}{_s}{r.Item2.ToString("0.000")}{_s}{r.Item3 * 100}{_s}{r.Item4 * 100}{_s}{r.Item5}");
|
||||
}
|
||||
|
||||
foreach (var e in errors)
|
||||
@@ -306,7 +342,8 @@ namespace Managing.Application.Tests
|
||||
}
|
||||
|
||||
var bestResult = result.OrderByDescending(b => b.Item3).FirstOrDefault();
|
||||
WriteCsvAnalyse($"Best result : {bestResult.Item1} - Rsi Period : {bestResult.Item2} - {bestResult.Item3} - SL : {bestResult.Item4}% - TP : {bestResult.Item5}%");
|
||||
WriteCsvAnalyse(
|
||||
$"Best result : {bestResult.Item1} - Rsi Period : {bestResult.Item2} - {bestResult.Item3} - SL : {bestResult.Item4}% - TP : {bestResult.Item5}%");
|
||||
|
||||
Assert.True(result.Any());
|
||||
}
|
||||
@@ -321,8 +358,8 @@ namespace Managing.Application.Tests
|
||||
{
|
||||
if (!string.IsNullOrEmpty(fileIdentifier))
|
||||
_analysePath += $"-{fileIdentifier}-{DateTime.Now.ToString("dd-MM-HH-mm")}.csv";
|
||||
|
||||
File.AppendAllLines(_analysePath , new[] { line });
|
||||
|
||||
File.AppendAllLines(_analysePath, new[] { line });
|
||||
}
|
||||
|
||||
private void WriteCsvErrors(string line)
|
||||
@@ -335,12 +372,14 @@ namespace Managing.Application.Tests
|
||||
WriteCsvAnalyse("", fileIdentifier);
|
||||
}
|
||||
|
||||
private decimal GetTotalTrades(List<int> periodRange, List<decimal> stopLossRange, List<decimal> takeProfitRange)
|
||||
private decimal GetTotalTrades(List<int> periodRange, List<decimal> stopLossRange,
|
||||
List<decimal> takeProfitRange)
|
||||
{
|
||||
var stopLossRangeTotalTest = stopLossRange[1] / stopLossRange[2];
|
||||
var takeProfitRangeTotalTest = takeProfitRange[1] / takeProfitRange[2];
|
||||
|
||||
var totalTrades = GetTotalTradeForStopLossTakeProfit(stopLossRange, takeProfitRange) * stopLossRangeTotalTest * takeProfitRangeTotalTest;
|
||||
var totalTrades = GetTotalTradeForStopLossTakeProfit(stopLossRange, takeProfitRange) *
|
||||
stopLossRangeTotalTest * takeProfitRangeTotalTest;
|
||||
return totalTrades;
|
||||
}
|
||||
|
||||
@@ -406,4 +445,4 @@ namespace Managing.Application.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user