Update account/position and platform summary
This commit is contained in:
@@ -9,27 +9,30 @@ namespace Managing.Domain.Accounts;
|
||||
public class Account
|
||||
{
|
||||
[Id(0)]
|
||||
[Required] public string Name { get; set; }
|
||||
public int Id { get; set; }
|
||||
|
||||
[Id(1)]
|
||||
[Required] public TradingExchanges Exchange { get; set; }
|
||||
[Required] public string Name { get; set; }
|
||||
|
||||
[Id(2)]
|
||||
[Required] public AccountType Type { get; set; }
|
||||
[Required] public TradingExchanges Exchange { get; set; }
|
||||
|
||||
[Id(3)]
|
||||
public string Key { get; set; }
|
||||
[Required] public AccountType Type { get; set; }
|
||||
|
||||
[Id(4)]
|
||||
public string Secret { get; set; }
|
||||
public string Key { get; set; }
|
||||
|
||||
[Id(5)]
|
||||
public User User { get; set; }
|
||||
public string Secret { get; set; }
|
||||
|
||||
[Id(6)]
|
||||
public List<Balance> Balances { get; set; }
|
||||
public User User { get; set; }
|
||||
|
||||
[Id(7)]
|
||||
public List<Balance> Balances { get; set; }
|
||||
|
||||
[Id(8)]
|
||||
public bool IsGmxInitialized { get; set; } = false;
|
||||
|
||||
public bool IsPrivyWallet => Type == AccountType.Privy;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using Exilion.TradingAtomics;
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Trades;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Shared.Helpers;
|
||||
@@ -97,4 +99,94 @@ public static class TradingHelpers
|
||||
|
||||
return traders;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the total fees for a position based on GMX V2 fee structure
|
||||
/// </summary>
|
||||
/// <param name="position">The position to calculate fees for</param>
|
||||
/// <returns>The total fees for the position</returns>
|
||||
public static decimal CalculatePositionFees(Position position)
|
||||
{
|
||||
var (uiFees, gasFees) = CalculatePositionFeesBreakdown(position);
|
||||
return uiFees + gasFees;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the UI and Gas fees breakdown for a position based on GMX V2 fee structure
|
||||
/// </summary>
|
||||
/// <param name="position">The position to calculate fees for</param>
|
||||
/// <returns>A tuple containing (uiFees, gasFees)</returns>
|
||||
public static (decimal uiFees, decimal gasFees) CalculatePositionFeesBreakdown(Position position)
|
||||
{
|
||||
decimal uiFees = 0;
|
||||
decimal gasFees = 0;
|
||||
|
||||
if (position?.Open?.Price <= 0 || position?.Open?.Quantity <= 0)
|
||||
{
|
||||
return (uiFees, gasFees); // Return 0 if position data is invalid
|
||||
}
|
||||
|
||||
// Calculate position size in USD (leverage is already included in quantity calculation)
|
||||
var positionSizeUsd = (position.Open.Price * position.Open.Quantity) * position.Open.Leverage;
|
||||
|
||||
// UI Fee: 0.1% of position size paid on opening
|
||||
var uiFeeOpen = positionSizeUsd * Constants.GMX.Config.UiFeeRate; // Fee paid on opening
|
||||
uiFees += uiFeeOpen;
|
||||
|
||||
// UI Fee: 0.1% of position size paid on closing - only if position was actually closed
|
||||
// Check which closing trade was executed (StopLoss, TakeProfit1, or TakeProfit2)
|
||||
if (position.StopLoss?.Status == TradeStatus.Filled)
|
||||
{
|
||||
var stopLossPositionSizeUsd = (position.StopLoss.Price * position.StopLoss.Quantity) * position.StopLoss.Leverage;
|
||||
var uiFeeClose = stopLossPositionSizeUsd * Constants.GMX.Config.UiFeeRate; // Fee paid on closing via StopLoss
|
||||
uiFees += uiFeeClose;
|
||||
}
|
||||
else if (position.TakeProfit1?.Status == TradeStatus.Filled)
|
||||
{
|
||||
var takeProfit1PositionSizeUsd = (position.TakeProfit1.Price * position.TakeProfit1.Quantity) * position.TakeProfit1.Leverage;
|
||||
var uiFeeClose = takeProfit1PositionSizeUsd * Constants.GMX.Config.UiFeeRate; // Fee paid on closing via TakeProfit1
|
||||
uiFees += uiFeeClose;
|
||||
}
|
||||
else if (position.TakeProfit2?.Status == TradeStatus.Filled)
|
||||
{
|
||||
var takeProfit2PositionSizeUsd = (position.TakeProfit2.Price * position.TakeProfit2.Quantity) * position.TakeProfit2.Leverage;
|
||||
var uiFeeClose = takeProfit2PositionSizeUsd * Constants.GMX.Config.UiFeeRate; // Fee paid on closing via TakeProfit2
|
||||
uiFees += uiFeeClose;
|
||||
}
|
||||
|
||||
// Gas Fee: $0.15 for opening position only
|
||||
// Closing is handled by oracle, so no gas fee for closing
|
||||
gasFees += Constants.GMX.Config.GasFeePerTransaction;
|
||||
|
||||
return (uiFees, gasFees);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates UI fees for opening a position
|
||||
/// </summary>
|
||||
/// <param name="positionSizeUsd">The position size in USD</param>
|
||||
/// <returns>The UI fees for opening</returns>
|
||||
public static decimal CalculateOpeningUiFees(decimal positionSizeUsd)
|
||||
{
|
||||
return positionSizeUsd * Constants.GMX.Config.UiFeeRate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates UI fees for closing a position
|
||||
/// </summary>
|
||||
/// <param name="positionSizeUsd">The position size in USD</param>
|
||||
/// <returns>The UI fees for closing</returns>
|
||||
public static decimal CalculateClosingUiFees(decimal positionSizeUsd)
|
||||
{
|
||||
return positionSizeUsd * Constants.GMX.Config.UiFeeRate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates gas fees for opening a position
|
||||
/// </summary>
|
||||
/// <returns>The gas fees for opening (fixed at $0.15)</returns>
|
||||
public static decimal CalculateOpeningGasFees()
|
||||
{
|
||||
return Constants.GMX.Config.GasFeePerTransaction;
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,11 @@ namespace Managing.Domain.Trades
|
||||
[GenerateSerializer]
|
||||
public class Position
|
||||
{
|
||||
public Position(Guid identifier, string accountName, TradeDirection originDirection, Ticker ticker,
|
||||
public Position(Guid identifier, int accountId, TradeDirection originDirection, Ticker ticker,
|
||||
LightMoneyManagement moneyManagement, PositionInitiator initiator, DateTime date, User user)
|
||||
{
|
||||
Identifier = identifier;
|
||||
AccountName = accountName;
|
||||
AccountId = accountId;
|
||||
OriginDirection = originDirection;
|
||||
Ticker = ticker;
|
||||
MoneyManagement = moneyManagement;
|
||||
@@ -23,9 +23,9 @@ namespace Managing.Domain.Trades
|
||||
User = user;
|
||||
}
|
||||
|
||||
[Id(0)] [Required] public string AccountName { get; set; }
|
||||
[Id(0)] [Required] public DateTime Date { get; set; }
|
||||
|
||||
[Id(1)] [Required] public DateTime Date { get; set; }
|
||||
[Id(1)] [Required] public int AccountId { get; set; }
|
||||
|
||||
[Id(2)] [Required] public TradeDirection OriginDirection { get; set; }
|
||||
|
||||
@@ -56,20 +56,24 @@ namespace Managing.Domain.Trades
|
||||
[JsonPropertyName("ProfitAndLoss")]
|
||||
public ProfitAndLoss ProfitAndLoss { get; set; }
|
||||
|
||||
[Id(10)] [Required] public PositionStatus Status { get; set; }
|
||||
[Id(10)] public decimal UiFees { get; set; }
|
||||
|
||||
[Id(11)] public string SignalIdentifier { get; set; }
|
||||
[Id(11)] public decimal GasFees { get; set; }
|
||||
|
||||
[Id(12)] [Required] public Guid Identifier { get; set; }
|
||||
[Id(12)] [Required] public PositionStatus Status { get; set; }
|
||||
|
||||
[Id(13)] [Required] public PositionInitiator Initiator { get; set; }
|
||||
[Id(13)] public string SignalIdentifier { get; set; }
|
||||
|
||||
[Id(14)] [Required] public User User { get; set; }
|
||||
[Id(14)] [Required] public Guid Identifier { get; set; }
|
||||
|
||||
[Id(15)] [Required] public PositionInitiator Initiator { get; set; }
|
||||
|
||||
[Id(16)] [Required] public User User { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Identifier of the bot or entity that initiated this position
|
||||
/// </summary>
|
||||
[Id(15)] [Required] public Guid InitiatorIdentifier { get; set; }
|
||||
[Id(17)] [Required] public Guid InitiatorIdentifier { get; set; }
|
||||
|
||||
public bool IsFinished()
|
||||
{
|
||||
@@ -80,5 +84,46 @@ namespace Managing.Domain.Trades
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the total fees for this position based on GMX V2 fee structure
|
||||
/// </summary>
|
||||
/// <returns>The total fees for the position</returns>
|
||||
public decimal CalculateTotalFees()
|
||||
{
|
||||
return UiFees + GasFees;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the net PnL after deducting fees
|
||||
/// </summary>
|
||||
/// <returns>The net PnL after fees</returns>
|
||||
public decimal GetNetPnL()
|
||||
{
|
||||
if (ProfitAndLoss?.Realized == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ProfitAndLoss.Realized - CalculateTotalFees();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the UI fees for this position
|
||||
/// </summary>
|
||||
/// <param name="uiFees">The UI fees to add</param>
|
||||
public void AddUiFees(decimal uiFees)
|
||||
{
|
||||
UiFees += uiFees;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the gas fees for this position
|
||||
/// </summary>
|
||||
/// <param name="gasFees">The gas fees to add</param>
|
||||
public void AddGasFees(decimal gasFees)
|
||||
{
|
||||
GasFees += gasFees;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user