From 4790a474d6470e4f000b2e6e13fbdeccaa715119 Mon Sep 17 00:00:00 2001 From: Jhonathan Abreu Date: Thu, 22 Jan 2026 12:51:52 -0400 Subject: [PATCH] Add PriceCurrency to Trade --- Common/Statistics/Trade.cs | 5 +++++ Common/Statistics/TradeBuilder.cs | 18 ++++++++++++------ Tests/Common/Statistics/TradeTests.cs | 8 ++++++-- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Common/Statistics/Trade.cs b/Common/Statistics/Trade.cs index 35ef2a35c6bb..5bc336136655 100644 --- a/Common/Statistics/Trade.cs +++ b/Common/Statistics/Trade.cs @@ -88,6 +88,11 @@ public List Symbols /// public decimal ExitPrice { get; set; } + /// + /// The currency of the prices (e.g. "USD") + /// + public string PriceCurrency { get; set; } + /// /// The gross profit/loss of the trade (as account currency) /// diff --git a/Common/Statistics/TradeBuilder.cs b/Common/Statistics/TradeBuilder.cs index b0b0cb010c30..52d55bb4e636 100644 --- a/Common/Statistics/TradeBuilder.cs +++ b/Common/Statistics/TradeBuilder.cs @@ -233,7 +233,8 @@ private void ProcessFillUsingFillToFill(OrderEvent fill, decimal orderFee, decim Direction = fill.FillQuantity > 0 ? TradeDirection.Long : TradeDirection.Short, Quantity = fill.AbsoluteFillQuantity, TotalFees = orderFee, - OrderIds = new HashSet() { fill.OrderId } + OrderIds = new HashSet() { fill.OrderId }, + PriceCurrency = fill.FillPriceCurrency } }, MinPrice = fill.FillPrice, @@ -257,7 +258,8 @@ private void ProcessFillUsingFillToFill(OrderEvent fill, decimal orderFee, decim Direction = fill.FillQuantity > 0 ? TradeDirection.Long : TradeDirection.Short, Quantity = fill.AbsoluteFillQuantity, TotalFees = orderFee, - OrderIds = new HashSet() { fill.OrderId } + OrderIds = new HashSet() { fill.OrderId }, + PriceCurrency = fill.FillPriceCurrency }); } else @@ -306,7 +308,8 @@ private void ProcessFillUsingFillToFill(OrderEvent fill, decimal orderFee, decim TotalFees = trade.TotalFees + (orderFeeAssigned ? 0 : orderFee), MAE = Math.Round((trade.Direction == TradeDirection.Long ? position.MinPrice - trade.EntryPrice : trade.EntryPrice - position.MaxPrice) * absoluteUnexecutedQuantity * conversionRate * multiplier, 2), MFE = Math.Round((trade.Direction == TradeDirection.Long ? position.MaxPrice - trade.EntryPrice : trade.EntryPrice - position.MinPrice) * absoluteUnexecutedQuantity * conversionRate * multiplier, 2), - OrderIds = new HashSet([..trade.OrderIds, fill.OrderId]) + OrderIds = new HashSet([..trade.OrderIds, fill.OrderId]), + PriceCurrency = fill.FillPriceCurrency }; AddNewTrade(newTrade, fill); @@ -335,7 +338,8 @@ private void ProcessFillUsingFillToFill(OrderEvent fill, decimal orderFee, decim Direction = fill.FillQuantity > 0 ? TradeDirection.Long : TradeDirection.Short, Quantity = fill.AbsoluteFillQuantity, TotalFees = 0, - OrderIds = new HashSet() { fill.OrderId } + OrderIds = new HashSet() { fill.OrderId }, + PriceCurrency = fill.FillPriceCurrency } }; position.MinPrice = fill.FillPrice; @@ -423,7 +427,8 @@ private void ProcessFillUsingFlatToFlat(OrderEvent fill, decimal orderFee, decim TotalFees = position.TotalFees, MAE = Math.Round((direction == TradeDirection.Long ? position.MinPrice - entryAveragePrice : entryAveragePrice - position.MaxPrice) * Math.Abs(totalEntryQuantity) * conversionRate * multiplier, 2), MFE = Math.Round((direction == TradeDirection.Long ? position.MaxPrice - entryAveragePrice : entryAveragePrice - position.MinPrice) * Math.Abs(totalEntryQuantity) * conversionRate * multiplier, 2), - OrderIds = relatedOrderIds + OrderIds = relatedOrderIds, + PriceCurrency = fill.FillPriceCurrency }; AddNewTrade(trade, fill); @@ -526,7 +531,8 @@ private void ProcessFillUsingFlatToReduced(OrderEvent fill, decimal orderFee, de TotalFees = position.TotalFees, MAE = Math.Round((direction == TradeDirection.Long ? position.MinPrice - entryPrice : entryPrice - position.MaxPrice) * Math.Abs(totalExecutedQuantity) * conversionRate * multiplier, 2), MFE = Math.Round((direction == TradeDirection.Long ? position.MaxPrice - entryPrice : entryPrice - position.MinPrice) * Math.Abs(totalExecutedQuantity) * conversionRate * multiplier, 2), - OrderIds = relatedOrderIds + OrderIds = relatedOrderIds, + PriceCurrency = fill.FillPriceCurrency }; AddNewTrade(trade, fill); diff --git a/Tests/Common/Statistics/TradeTests.cs b/Tests/Common/Statistics/TradeTests.cs index 87599010b188..f86d293a4759 100644 --- a/Tests/Common/Statistics/TradeTests.cs +++ b/Tests/Common/Statistics/TradeTests.cs @@ -42,6 +42,7 @@ public void JsonSerializationRoundTrip() Assert.AreEqual(trade.TotalFees, deserializedTrade.TotalFees); Assert.AreEqual(trade.MAE, deserializedTrade.MAE); Assert.AreEqual(trade.MFE, deserializedTrade.MFE); + Assert.AreEqual(trade.PriceCurrency, deserializedTrade.PriceCurrency); // For backwards compatibility, also verify Symbol property is set correctly Assert.IsNotNull(trade.Symbol); @@ -81,7 +82,8 @@ public void CanDeserializeOldFormatWithSymbol() ""Duration"": ""00:20:00"", ""EndTradeDrawdown"": -10.0, ""IsWin"": false, - ""OrderIds"": [] + ""OrderIds"": [], + ""PriceCurrency"": ""USD"" }"; var deserializedTrade = JsonConvert.DeserializeObject(jsonTrade); Assert.IsNotNull(deserializedTrade); @@ -96,6 +98,7 @@ public void CanDeserializeOldFormatWithSymbol() Assert.AreEqual(2.5m, deserializedTrade.TotalFees); Assert.AreEqual(-5m, deserializedTrade.MAE); Assert.AreEqual(30m, deserializedTrade.MFE); + Assert.AreEqual("USD", deserializedTrade.PriceCurrency); // For backwards compatibility, also verify Symbol property is set correctly Assert.IsNotNull(deserializedTrade.Symbol); Assert.AreEqual(deserializedTrade.Symbols[0], deserializedTrade.Symbol); @@ -117,7 +120,8 @@ private static Trade MakeTrade() ProfitLoss = 20, TotalFees = 2.5m, MAE = -5, - MFE = 30 + MFE = 30, + PriceCurrency = "USD" }; return trade; }