Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Common/Statistics/Trade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ public List<Symbol> Symbols
/// </summary>
public decimal ExitPrice { get; set; }

/// <summary>
/// The currency of the prices (e.g. "USD")
/// </summary>
public string PriceCurrency { get; set; }

/// <summary>
/// The gross profit/loss of the trade (as account currency)
/// </summary>
Expand Down
18 changes: 12 additions & 6 deletions Common/Statistics/TradeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>() { fill.OrderId }
OrderIds = new HashSet<int>() { fill.OrderId },
PriceCurrency = fill.FillPriceCurrency
}
},
MinPrice = fill.FillPrice,
Expand All @@ -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<int>() { fill.OrderId }
OrderIds = new HashSet<int>() { fill.OrderId },
PriceCurrency = fill.FillPriceCurrency
});
}
else
Expand Down Expand Up @@ -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<int>([..trade.OrderIds, fill.OrderId])
OrderIds = new HashSet<int>([..trade.OrderIds, fill.OrderId]),
PriceCurrency = fill.FillPriceCurrency
};

AddNewTrade(newTrade, fill);
Expand Down Expand Up @@ -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<int>() { fill.OrderId }
OrderIds = new HashSet<int>() { fill.OrderId },
PriceCurrency = fill.FillPriceCurrency
}
};
position.MinPrice = fill.FillPrice;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 6 additions & 2 deletions Tests/Common/Statistics/TradeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -81,7 +82,8 @@ public void CanDeserializeOldFormatWithSymbol()
""Duration"": ""00:20:00"",
""EndTradeDrawdown"": -10.0,
""IsWin"": false,
""OrderIds"": []
""OrderIds"": [],
""PriceCurrency"": ""USD""
}";
var deserializedTrade = JsonConvert.DeserializeObject<Trade>(jsonTrade);
Assert.IsNotNull(deserializedTrade);
Expand All @@ -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);
Expand All @@ -117,7 +120,8 @@ private static Trade MakeTrade()
ProfitLoss = 20,
TotalFees = 2.5m,
MAE = -5,
MFE = 30
MFE = 30,
PriceCurrency = "USD"
};
return trade;
}
Expand Down
Loading