229 lines
8.6 KiB
C#
229 lines
8.6 KiB
C#
using System.Numerics;
|
|
using Managing.ABI.GmxV2.SyntheticsReader.ContractDefinition;
|
|
using Managing.Common;
|
|
using Managing.Core;
|
|
using Managing.Domain.Candles;
|
|
using Managing.Domain.MoneyManagements;
|
|
using Managing.Domain.Trades;
|
|
using Managing.Domain.Users;
|
|
using Managing.Infrastructure.Evm.Models.Gmx.v2;
|
|
using Managing.Infrastructure.Evm.Models.Proxy;
|
|
using Nethereum.Web3;
|
|
using static Managing.Common.Enums;
|
|
|
|
namespace Managing.Infrastructure.Evm.Services.Gmx;
|
|
|
|
internal static class GmxV2Mappers
|
|
{
|
|
public static Trade Map(GmxV2Position position, Ticker ticker)
|
|
{
|
|
var entryPrice = GmxV2Helpers.GetEntryPrice(position.SizeInUsd, position.SizeInTokens,
|
|
position.TokenData.Decimals);
|
|
var parsedEntryPrice = GmxHelpers.FormatAmount(entryPrice, Constants.GMX.Config.Decimals.USD - 2, 4);
|
|
|
|
var collateralLeverage = CalculateCollateralAndLeverage(position.SizeInUsd, position.CollateralAmount);
|
|
var trade = new Trade(
|
|
DateHelpers.GetFromUnixTimestamp((int)position.IncreasedAtTime),
|
|
position.IsLong ? TradeDirection.Long : TradeDirection.Short,
|
|
TradeStatus.Filled,
|
|
TradeType.Limit,
|
|
ticker,
|
|
collateralLeverage.collateral / parsedEntryPrice,
|
|
parsedEntryPrice,
|
|
collateralLeverage.leverage,
|
|
position.Key,
|
|
""
|
|
);
|
|
|
|
return trade;
|
|
}
|
|
|
|
public static List<Trade> Map(List<GmxV2Order> orders)
|
|
{
|
|
var trades = new List<Trade>();
|
|
|
|
foreach (var order in orders)
|
|
{
|
|
var shortToken = TokenV2Service.GetTokenByAddress(order.InitialCollateralTokenAddress);
|
|
var ticker = GmxV2Helpers.GetTicker(order.MarketAddress);
|
|
var indexToken = TokenV2Service.GetByTicker(ticker);
|
|
var sizeDelta = GmxHelpers.FormatAmount(order.SizeDeltaUsd, Constants.GMX.Config.Decimals.USD, 4);
|
|
var triggerPrice = GmxV2Helpers.ParseContractPrice(order.ContractTriggerPrice, indexToken.Decimals, true);
|
|
var quantity = sizeDelta / triggerPrice;
|
|
var initialCollateral =
|
|
GmxV2Helpers.ParseContractPrice(order.InitialCollateralDeltaAmount, shortToken.Decimals);
|
|
var leverage = sizeDelta == 0 || initialCollateral == 0 ? 0 : sizeDelta / initialCollateral;
|
|
|
|
var trade = new Trade(
|
|
order.Date,
|
|
order.IsLong ? TradeDirection.Long : TradeDirection.Short,
|
|
TradeStatus.PendingOpen,
|
|
GmxV2Helpers.GetTradeType(order.OrderType),
|
|
ticker,
|
|
Convert.ToDecimal(quantity),
|
|
Convert.ToDecimal(triggerPrice),
|
|
leverage,
|
|
"",
|
|
""
|
|
);
|
|
|
|
trades.Add(trade);
|
|
}
|
|
|
|
return trades;
|
|
}
|
|
//
|
|
// public static GmxV2Position MapPosition(GmxV2Service.PositionInfoDTO positionInfo)
|
|
// {
|
|
// return new GmxV2Position
|
|
// {
|
|
// PositionKey = GetPositionKeyV2(
|
|
// positionInfo.Position.Account,
|
|
// positionInfo.Position.Market,
|
|
// positionInfo.Position.CollateralToken,
|
|
// positionInfo.Position.IsLong
|
|
// ),
|
|
// SizeInUsd = positionInfo.Position.SizeInUsd,
|
|
// CollateralAmount = positionInfo.Position.CollateralAmount,
|
|
// IncreasedAtTime = positionInfo.Position.IncreasedAtTime,
|
|
// IsLong = positionInfo.Position.IsLong,
|
|
// Leverage = CalculateLeverage(positionInfo.Position.SizeInUsd, positionInfo.Position.CollateralAmount)
|
|
// };
|
|
// }
|
|
|
|
private static (decimal collateral, decimal leverage) CalculateCollateralAndLeverage(BigInteger sizeInUsd,
|
|
BigInteger collateralAmount)
|
|
{
|
|
if (collateralAmount == 0) return (0m, 0m);
|
|
const int collateralDecimals = 6;
|
|
var size = Web3.Convert.FromWei(sizeInUsd, 30);
|
|
var collateral = Web3.Convert.FromWei(collateralAmount, collateralDecimals);
|
|
return (collateral, collateral == 0 ? 0 : Math.Round(size / collateral));
|
|
}
|
|
|
|
public static List<MarketPrices> Map(List<ABI.GmxV2.Reader.ContractDefinition.MarketPrices> marketPrices)
|
|
{
|
|
return marketPrices.Select(mp => new MarketPrices
|
|
{
|
|
IndexTokenPrice = mp.IndexTokenPrice,
|
|
LongTokenPrice = mp.LongTokenPrice,
|
|
ShortTokenPrice = mp.ShortTokenPrice
|
|
}).ToList();
|
|
}
|
|
|
|
public static Candle Map(List<double> marketPrices, Ticker ticker, Timeframe timeframe, int timeBetween)
|
|
{
|
|
return new Candle()
|
|
{
|
|
Date = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0] + timeBetween).AddSeconds(-1),
|
|
OpenTime = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0]),
|
|
Open = Convert.ToDecimal(marketPrices[1]),
|
|
High = Convert.ToDecimal(marketPrices[2]),
|
|
Low = Convert.ToDecimal(marketPrices[3]),
|
|
Close = Convert.ToDecimal(marketPrices[4]),
|
|
Exchange = TradingExchanges.Evm,
|
|
Ticker = ticker.ToString(),
|
|
Timeframe = timeframe
|
|
};
|
|
}
|
|
|
|
public static List<Ticker> Map(GmxV2TokenList tokenList)
|
|
{
|
|
var tokens = new List<Ticker>();
|
|
foreach (var t in tokenList.Tokens)
|
|
{
|
|
try
|
|
{
|
|
var ticker = MiscExtensions.ParseEnum<Ticker>(t.Symbol);
|
|
tokens.Add(ticker);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine($"Could not parse ticker for symbol {t.Symbol}: {e.Message}");
|
|
}
|
|
}
|
|
|
|
return tokens;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps raw GMX positions fetched from the proxy/contract to domain Position objects.
|
|
/// </summary>
|
|
/// <param name="resultPositions">List of GmxPosition objects from the proxy.</param>
|
|
/// <returns>List of domain Position objects.</returns>
|
|
/// <remarks>
|
|
/// Assumes GmxPosition contains necessary details like Account, Market, CollateralToken, IsLong, etc.
|
|
/// Requires resolution of MoneyManagement dependency.
|
|
/// </remarks>
|
|
public static List<Position> Map(List<GmxPosition> resultPositions)
|
|
{
|
|
var positions = new List<Position>();
|
|
foreach (var gmxPosition in resultPositions)
|
|
{
|
|
try
|
|
{
|
|
var direction = MiscExtensions.ParseEnum<TradeDirection>(gmxPosition.Direction);
|
|
var ticker = MiscExtensions.ParseEnum<Ticker>(gmxPosition.Ticker);
|
|
var position = new Position("", "",
|
|
direction,
|
|
ticker,
|
|
new MoneyManagement(),
|
|
PositionInitiator.User,
|
|
gmxPosition.Date,
|
|
new User());
|
|
position.Open = new Trade(position.Date, direction, TradeStatus.Filled, TradeType.Market, ticker,
|
|
(decimal)gmxPosition.Quantity, (decimal)gmxPosition.Price, (decimal)gmxPosition.Leverage,
|
|
gmxPosition.Open.ExchangeOrderId, "");
|
|
|
|
if (gmxPosition.TakeProfit1 != null)
|
|
{
|
|
position.TakeProfit1 = Map(gmxPosition.TakeProfit1);
|
|
}
|
|
|
|
if (gmxPosition.StopLoss != null)
|
|
{
|
|
position.StopLoss = Map(gmxPosition.StopLoss);
|
|
}
|
|
|
|
position.ProfitAndLoss = new ProfitAndLoss()
|
|
{
|
|
Realized = (decimal)gmxPosition.Pnl
|
|
};
|
|
|
|
position.Status = MiscExtensions.ParseEnum<PositionStatus>(gmxPosition.Status);
|
|
positions.Add(position);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(
|
|
$"Error mapping GMX position {gmxPosition?.ExchangeOrderId}: {ex.Message} \n StackTrace: {ex.StackTrace}");
|
|
}
|
|
}
|
|
|
|
return positions;
|
|
}
|
|
|
|
private static Trade Map(GmxTrade gmxPosition)
|
|
{
|
|
return new Trade(gmxPosition.Date,
|
|
MiscExtensions.ParseEnum<TradeDirection>(gmxPosition.Direction),
|
|
MiscExtensions.ParseEnum<TradeStatus>(gmxPosition.Status),
|
|
MiscExtensions.ParseEnum<TradeType>(gmxPosition.TradeType),
|
|
MiscExtensions.ParseEnum<Ticker>(gmxPosition.Ticker),
|
|
(decimal)gmxPosition.Quantity,
|
|
(decimal)gmxPosition.Price,
|
|
gmxPosition.Leverage,
|
|
gmxPosition.ExchangeOrderId, "");
|
|
}
|
|
|
|
public static List<Trade> Map(List<GmxTrade> resultPositions)
|
|
{
|
|
var trades = new List<Trade>();
|
|
foreach (var gmxPosition in resultPositions)
|
|
{
|
|
trades.Add(Map(gmxPosition));
|
|
}
|
|
|
|
return trades;
|
|
}
|
|
} |