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,5 +1,7 @@
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Bots;
|
||||
|
||||
public class BotBackup
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Managing.Application.Strategies;
|
||||
using Managing.Domain.Strategies;
|
||||
using Managing.Domain.Strategies;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Scenarios;
|
||||
@@ -14,16 +13,25 @@ public static class ScenarioHelpers
|
||||
IStrategy result = strategy.Type switch
|
||||
{
|
||||
StrategyType.StDev => new StDevContext(strategy.Name, strategy.Timeframe, strategy.Period.Value),
|
||||
StrategyType.RsiDivergence => new RSIDivergenceStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value),
|
||||
StrategyType.RsiDivergenceConfirm => new RSIDivergenceConfirmStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value),
|
||||
StrategyType.MacdCross => new MACDCrossStrategy(strategy.Name, strategy.Timeframe, strategy.FastPeriods.Value, strategy.SlowPeriods.Value, strategy.SignalPeriods.Value),
|
||||
StrategyType.RsiDivergence => new RSIDivergenceStrategy(strategy.Name, strategy.Timeframe,
|
||||
strategy.Period.Value),
|
||||
StrategyType.RsiDivergenceConfirm => new RSIDivergenceConfirmStrategy(strategy.Name, strategy.Timeframe,
|
||||
strategy.Period.Value),
|
||||
StrategyType.MacdCross => new MACDCrossStrategy(strategy.Name, strategy.Timeframe,
|
||||
strategy.FastPeriods.Value, strategy.SlowPeriods.Value, strategy.SignalPeriods.Value),
|
||||
StrategyType.EmaCross => new EmaCrossStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value),
|
||||
StrategyType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value),
|
||||
StrategyType.SuperTrend => new SuperTrendStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value, strategy.Multiplier.Value),
|
||||
StrategyType.ChandelierExit => new ChandelierExitStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value, strategy.Multiplier.Value),
|
||||
StrategyType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersStrategy(strategy.Name, strategy.Timeframe,
|
||||
strategy.Period.Value),
|
||||
StrategyType.SuperTrend => new SuperTrendStrategy(strategy.Name, strategy.Timeframe,
|
||||
strategy.Period.Value, strategy.Multiplier.Value),
|
||||
StrategyType.ChandelierExit => new ChandelierExitStrategy(strategy.Name, strategy.Timeframe,
|
||||
strategy.Period.Value, strategy.Multiplier.Value),
|
||||
StrategyType.EmaTrend => new EmaTrendStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value),
|
||||
StrategyType.StochRsiTrend => new StochRsiTrendStrategy(strategy.Name, strategy.Timeframe, strategy.Period.Value, strategy.StochPeriods.Value, strategy.SignalPeriods.Value, strategy.SmoothPeriods.Value),
|
||||
StrategyType.Stc => new STCStrategy(strategy.Name, strategy.Timeframe, strategy.CyclePeriods.Value, strategy.FastPeriods.Value, strategy.SlowPeriods.Value),
|
||||
StrategyType.StochRsiTrend => new StochRsiTrendStrategy(strategy.Name, strategy.Timeframe,
|
||||
strategy.Period.Value, strategy.StochPeriods.Value, strategy.SignalPeriods.Value,
|
||||
strategy.SmoothPeriods.Value),
|
||||
StrategyType.Stc => new STCStrategy(strategy.Name, strategy.Timeframe, strategy.CyclePeriods.Value,
|
||||
strategy.FastPeriods.Value, strategy.SlowPeriods.Value),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
@@ -63,11 +71,13 @@ public static class ScenarioHelpers
|
||||
{
|
||||
strategy.Period = period.Value;
|
||||
}
|
||||
|
||||
break;
|
||||
case StrategyType.MacdCross:
|
||||
if (!fastPeriods.HasValue || !slowPeriods.HasValue || !signalPeriods.HasValue)
|
||||
{
|
||||
throw new Exception($"Missing fastPeriods or slowPeriods or signalPeriods, for {strategy.Type} strategy type");
|
||||
throw new Exception(
|
||||
$"Missing fastPeriods or slowPeriods or signalPeriods, for {strategy.Type} strategy type");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -75,6 +85,7 @@ public static class ScenarioHelpers
|
||||
strategy.SlowPeriods = slowPeriods;
|
||||
strategy.SignalPeriods = signalPeriods;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
case StrategyType.ThreeWhiteSoldiers:
|
||||
@@ -90,6 +101,7 @@ public static class ScenarioHelpers
|
||||
strategy.Period = period;
|
||||
strategy.Multiplier = multiplier;
|
||||
}
|
||||
|
||||
break;
|
||||
case StrategyType.StochRsiTrend:
|
||||
if (!period.HasValue
|
||||
@@ -97,7 +109,8 @@ public static class ScenarioHelpers
|
||||
|| !signalPeriods.HasValue
|
||||
|| !smoothPeriods.HasValue)
|
||||
{
|
||||
throw new Exception($"Missing period, stochPeriods, signalPeriods, smoothPeriods for {strategy.Type} strategy type");
|
||||
throw new Exception(
|
||||
$"Missing period, stochPeriods, signalPeriods, smoothPeriods for {strategy.Type} strategy type");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -106,11 +119,13 @@ public static class ScenarioHelpers
|
||||
strategy.SignalPeriods = signalPeriods;
|
||||
strategy.SmoothPeriods = smoothPeriods;
|
||||
}
|
||||
|
||||
break;
|
||||
case StrategyType.Stc:
|
||||
if (!fastPeriods.HasValue || !slowPeriods.HasValue || !cyclePeriods.HasValue)
|
||||
{
|
||||
throw new Exception($"Missing fastPeriods or slowPeriods or cyclePeriods, for {strategy.Type} strategy type");
|
||||
throw new Exception(
|
||||
$"Missing fastPeriods or slowPeriods or cyclePeriods, for {strategy.Type} strategy type");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -118,6 +133,7 @@ public static class ScenarioHelpers
|
||||
strategy.SlowPeriods = slowPeriods;
|
||||
strategy.CyclePeriods = cyclePeriods;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -145,4 +161,4 @@ public static class ScenarioHelpers
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,8 @@ namespace Managing.Domain.Shared.Helpers;
|
||||
|
||||
public static class TradingBox
|
||||
{
|
||||
public static Signal GetSignal(HashSet<Candle> newCandles, HashSet<IStrategy> strategies, HashSet<Signal> previousSignal)
|
||||
public static Signal GetSignal(HashSet<Candle> newCandles, HashSet<IStrategy> strategies,
|
||||
HashSet<Signal> previousSignal)
|
||||
{
|
||||
var signalOnCandles = new HashSet<Signal>();
|
||||
foreach (var strategy in strategies)
|
||||
@@ -35,10 +36,12 @@ public static class TradingBox
|
||||
return null;
|
||||
|
||||
var data = newCandles.First();
|
||||
return ComputeSignals(strategies, signalOnCandles, MiscExtensions.ParseEnum<Ticker>(data.Ticker), data.Timeframe);
|
||||
return ComputeSignals(strategies, signalOnCandles, MiscExtensions.ParseEnum<Ticker>(data.Ticker),
|
||||
data.Timeframe);
|
||||
}
|
||||
|
||||
public static Signal ComputeSignals(HashSet<IStrategy> strategies, HashSet<Signal> signalOnCandles, Ticker ticker, Timeframe timeframe)
|
||||
public static Signal ComputeSignals(HashSet<IStrategy> strategies, HashSet<Signal> signalOnCandles, Ticker ticker,
|
||||
Timeframe timeframe)
|
||||
{
|
||||
Signal signal = null;
|
||||
if (strategies.Count > 1)
|
||||
@@ -49,34 +52,36 @@ public static class TradingBox
|
||||
var validContext = true;
|
||||
|
||||
if (contextStrategiesCount > 0 &&
|
||||
signalOnCandles.Count(s => s.SignalType == SignalType.Context) != contextStrategiesCount)
|
||||
signalOnCandles.Count(s => s.SignalType == SignalType.Context) != contextStrategiesCount)
|
||||
{
|
||||
validContext = false;
|
||||
}
|
||||
|
||||
if (signals.All(s => s.Direction == TradeDirection.Long) && trendSignal.All(t => t.Direction == TradeDirection.Long) && validContext)
|
||||
if (signals.All(s => s.Direction == TradeDirection.Long) &&
|
||||
trendSignal.All(t => t.Direction == TradeDirection.Long) && validContext)
|
||||
{
|
||||
signal = new Signal(
|
||||
ticker,
|
||||
TradeDirection.Long,
|
||||
Confidence.High,
|
||||
signals.Last().Candle,
|
||||
signals.Last().Date,
|
||||
signals.Last().Exchange,
|
||||
timeframe,
|
||||
StrategyType.Composite, SignalType.Signal);
|
||||
ticker,
|
||||
TradeDirection.Long,
|
||||
Confidence.High,
|
||||
signals.Last().Candle,
|
||||
signals.Last().Date,
|
||||
signals.Last().Exchange,
|
||||
timeframe,
|
||||
StrategyType.Composite, SignalType.Signal);
|
||||
}
|
||||
else if (signals.All(s => s.Direction == TradeDirection.Short) && trendSignal.All(t => t.Direction == TradeDirection.Short) && validContext)
|
||||
else if (signals.All(s => s.Direction == TradeDirection.Short) &&
|
||||
trendSignal.All(t => t.Direction == TradeDirection.Short) && validContext)
|
||||
{
|
||||
signal = new Signal(
|
||||
ticker,
|
||||
TradeDirection.Short,
|
||||
Confidence.High,
|
||||
signals.Last().Candle,
|
||||
signals.Last().Date,
|
||||
signals.Last().Exchange,
|
||||
timeframe,
|
||||
StrategyType.Composite, SignalType.Signal);
|
||||
ticker,
|
||||
TradeDirection.Short,
|
||||
Confidence.High,
|
||||
signals.Last().Candle,
|
||||
signals.Last().Date,
|
||||
signals.Last().Exchange,
|
||||
timeframe,
|
||||
StrategyType.Composite, SignalType.Signal);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -88,7 +93,8 @@ public static class TradingBox
|
||||
return signal;
|
||||
}
|
||||
|
||||
public static MoneyManagement GetBestMoneyManagement(List<Candle> candles, List<Position> positions, MoneyManagement originMoneyManagement)
|
||||
public static MoneyManagement GetBestMoneyManagement(List<Candle> candles, List<Position> positions,
|
||||
MoneyManagement originMoneyManagement)
|
||||
{
|
||||
// Foreach positions, identitify the price when the position is open
|
||||
// Then, foreach candles, get the maximum price before the next position
|
||||
@@ -120,11 +126,13 @@ public static class TradingBox
|
||||
return moneyManagement;
|
||||
}
|
||||
|
||||
public static (decimal Stoploss, decimal TakeProfit) GetBestSLTPForPosition(List<Candle> candles, Position position, Position nextPosition)
|
||||
public static (decimal Stoploss, decimal TakeProfit) GetBestSLTPForPosition(List<Candle> candles, Position position,
|
||||
Position nextPosition)
|
||||
{
|
||||
var stopLoss = 0M;
|
||||
var takeProfit = 0M;
|
||||
var candlesBeforeNextPosition = candles.Where(c => c.Date >= position.Date && c.Date <= (nextPosition == null ? candles.Last().Date : nextPosition.Date));
|
||||
var candlesBeforeNextPosition = candles.Where(c =>
|
||||
c.Date >= position.Date && c.Date <= (nextPosition == null ? candles.Last().Date : nextPosition.Date));
|
||||
|
||||
if (position.OriginDirection == TradeDirection.Long)
|
||||
{
|
||||
@@ -140,7 +148,7 @@ public static class TradingBox
|
||||
stopLoss = GetPercentageFromEntry(position.Open.Price, maxPrice);
|
||||
takeProfit = GetPercentageFromEntry(position.Open.Price, minPrice);
|
||||
}
|
||||
|
||||
|
||||
return (stopLoss, takeProfit);
|
||||
}
|
||||
|
||||
@@ -149,13 +157,18 @@ public static class TradingBox
|
||||
return Math.Abs(100 - ((100 * price) / entry));
|
||||
}
|
||||
|
||||
public static ProfitAndLoss GetProfitAndLoss(Position position, decimal quantity, decimal price)
|
||||
public static ProfitAndLoss GetProfitAndLoss(Position position, decimal quantity, decimal price, decimal leverage)
|
||||
{
|
||||
var orders = new List<Tuple<decimal, decimal>>
|
||||
{
|
||||
new Tuple<decimal, decimal>(position.Open.Quantity, position.Open.Price),
|
||||
new Tuple<decimal, decimal>(-quantity, price)
|
||||
};
|
||||
return new ProfitAndLoss(orders, position.OriginDirection);
|
||||
{
|
||||
new Tuple<decimal, decimal>(position.Open.Quantity, position.Open.Price),
|
||||
new Tuple<decimal, decimal>(-quantity, price)
|
||||
};
|
||||
|
||||
|
||||
var pnl = new ProfitAndLoss(orders, position.OriginDirection);
|
||||
// Apply leverage on the realized pnl
|
||||
pnl.Realized = pnl.Realized * leverage;
|
||||
return pnl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,30 @@
|
||||
using Managing.Domain.Scenarios;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Scenarios;
|
||||
using Managing.Domain.Strategies;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Statistics;
|
||||
|
||||
public class SpotlightOverview
|
||||
{
|
||||
[Required]
|
||||
public List<Spotlight> Spotlights { get; set; }
|
||||
[Required]
|
||||
public DateTime DateTime { get; set; }
|
||||
[Required] public List<Spotlight> Spotlights { get; set; }
|
||||
[Required] public DateTime DateTime { get; set; }
|
||||
public Guid Identifier { get; set; }
|
||||
public int ScenarioCount { get; set; }
|
||||
}
|
||||
|
||||
public class Spotlight
|
||||
{
|
||||
[Required]
|
||||
public Scenario Scenario { get; set; }
|
||||
[Required]
|
||||
public List<TickerSignal> TickerSignals { get; set; }
|
||||
[Required] public Scenario Scenario { get; set; }
|
||||
[Required] public List<TickerSignal> TickerSignals { get; set; }
|
||||
}
|
||||
|
||||
public class TickerSignal
|
||||
{
|
||||
[Required]
|
||||
public Ticker Ticker { get; set; }
|
||||
[Required]
|
||||
public List<Signal> FiveMinutes { get; set; }
|
||||
[Required]
|
||||
public List<Signal> FifteenMinutes { get; set; }
|
||||
[Required]
|
||||
public List<Signal> OneHour { get; set; }
|
||||
[Required]
|
||||
public List<Signal> FourHour { get; set; }
|
||||
[Required]
|
||||
public List<Signal> OneDay { get; set; }
|
||||
[Required] public Enums.Ticker Ticker { get; set; }
|
||||
[Required] public List<Signal> FiveMinutes { get; set; }
|
||||
[Required] public List<Signal> FifteenMinutes { get; set; }
|
||||
[Required] public List<Signal> OneHour { get; set; }
|
||||
[Required] public List<Signal> FourHour { get; set; }
|
||||
[Required] public List<Signal> OneDay { get; set; }
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Shared.Rules;
|
||||
using Managing.Domain.Strategies;
|
||||
using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Strategies;
|
||||
namespace Managing.Domain.Strategies;
|
||||
|
||||
public class EmaCrossStrategy : EmaBaseStrategy
|
||||
{
|
||||
@@ -28,20 +27,20 @@ public class EmaCrossStrategy : EmaBaseStrategy
|
||||
{
|
||||
var ema = Candles.GetEma(Period.Value).ToList();
|
||||
var emaCandles = MapEmaToCandle(ema, Candles.TakeLast(Period.Value));
|
||||
|
||||
|
||||
if (ema.Count == 0)
|
||||
return null;
|
||||
|
||||
var previousCandle = emaCandles[0];
|
||||
foreach (var currentCandle in emaCandles.Skip(1))
|
||||
{
|
||||
if (previousCandle.Close > (decimal)currentCandle.Ema &&
|
||||
if (previousCandle.Close > (decimal)currentCandle.Ema &&
|
||||
currentCandle.Close < (decimal)currentCandle.Ema)
|
||||
{
|
||||
AddSignal(currentCandle, Timeframe, TradeDirection.Short, Confidence.Medium);
|
||||
}
|
||||
|
||||
if (previousCandle.Close < (decimal)currentCandle.Ema &&
|
||||
if (previousCandle.Close < (decimal)currentCandle.Ema &&
|
||||
currentCandle.Close > (decimal)currentCandle.Ema)
|
||||
{
|
||||
AddSignal(currentCandle, Timeframe, TradeDirection.Long, Confidence.Medium);
|
||||
@@ -60,10 +59,11 @@ public class EmaCrossStrategy : EmaBaseStrategy
|
||||
|
||||
private void AddSignal(CandleEma 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))
|
||||
{
|
||||
Signals.AddItem(signal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Shared.Rules;
|
||||
using Managing.Domain.Strategies;
|
||||
using Managing.Domain.Strategies.Rules;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Strategies
|
||||
namespace Managing.Domain.Strategies
|
||||
{
|
||||
public class ThreeWhiteSoldiersStrategy : Strategy
|
||||
{
|
||||
@@ -52,4 +51,4 @@ namespace Managing.Application.Strategies
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user