//+------------------------------------------------------------------+
//|                                              TestTradeLoader.mq5 |
//+------------------------------------------------------------------+

#property script_show_inputs

#include <Trade_Replay_Engine/TradeRecord.mqh>

#define ASSERT(cond, label) \
   if(cond) Print("PASS: ", label); else Print("FAIL: ", label)

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(void)
  {
   CTradeRecord trade;
   trade.position_id = 1001;
   trade.symbol       = _Symbol;
   trade.order_type   = ORDER_TYPE_BUY;
   trade.volume       = 1.0;
   trade.entry_time   = D'2026.01.01 09:00';
   trade.exit_time    = D'2026.01.01 11:30';
   trade.entry_price  = 1.10000;
   trade.exit_price   = 1.10400;
   trade.stop_loss    = 1.09800;
   trade.take_profit  = 1.10500;
   trade.profit       = 400.0;
   trade.magic        = 0;
   trade.comment      = "test";

//--- DurationSeconds: 2.5 hours = 9000 seconds
   int expected_duration = 9000;
   ASSERT(trade.DurationSeconds() == expected_duration, "DurationSeconds == 9000");

//--- PipsProfit: buy, (1.10400 - 1.10000) / point_size
   double point_size    = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   double expected_pips  = (point_size > 0.0) ? (0.00400 / point_size) : 0.0;
   double actual_pips     = trade.PipsProfit();
   ASSERT(MathAbs(actual_pips - expected_pips) < 0.0001, "PipsProfit matches hand-computed value");

//--- RMultiple: profit / (risk_points * point_value * volume)
   double tick_value    = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double risk_points    = MathAbs(trade.entry_price - trade.stop_loss) / point_size;
   double risk_dollars    = risk_points * tick_value * trade.volume;
   double expected_r       = (risk_dollars != 0.0) ? (trade.profit / risk_dollars) : DBL_MAX;
   double actual_r          = trade.RMultiple();
   ASSERT(MathAbs(actual_r - expected_r) < 0.0001, "RMultiple matches hand-computed value");

//--- RMultiple with zero stop_loss returns sentinel
   CTradeRecord no_stop_trade = trade;
   no_stop_trade.stop_loss = 0.0;
   ASSERT(no_stop_trade.RMultiple() == DBL_MAX, "RMultiple returns DBL_MAX when stop_loss is zero");

//--- PipsProfit sign flips correctly for a sell
   CTradeRecord sell_trade = trade;
   sell_trade.order_type  = ORDER_TYPE_SELL;
   sell_trade.entry_price = 1.10400;
   sell_trade.exit_price  = 1.10000;
   double expected_sell_pips = (point_size > 0.0) ? (0.00400 / point_size) : 0.0;
   ASSERT(MathAbs(sell_trade.PipsProfit() - expected_sell_pips) < 0.0001,
          "PipsProfit correct for sell direction");

   Print("TestTradeLoader: all assertions complete.");
  }
//+------------------------------------------------------------------+