Profit calculation for pairs with Quote currency different than Account currency

Hi everyone,

I purchased AmiBroker Pro a few days ago and am already loving it! I see a lot of documentation is available (thank you Tomasz and everyone in the community for your contributions), and so far I was able to do everything I thought of, which is awesome!

I'm using x64 version 6.35.1, and two snippets of code that I used to generate the backtesting report are included at the end of the post. I don't understand why the Profit is calculated like it is. Here is more info:

I configured the currency preferences like this: preferences

And the USDCAD pair is configured like this: information

I exported data from my MT4, imported it into AmiBroker, and the daily OHLC prices are shown here: USDCAD%20MT4%20data

That part that I don't understand is the Profit column shown here: USDCAD

The entry and exit prices are what I see as the Open (light blue highlight), respectively the Close (light green highlight), for those days. That's exactly as expected.

The GrossPips is a custom metric, and I verified it by hand to be correctly calculated. Now the value of 1 Pips, for a trade size of 1 Lot (contract) is $10 for XXXUSD pairs, but 10 YYY currency for ABCYYY pairs. Based on that, I expected the Profit for the trade in the first row to be -23.9 Pips * 10 CAD = -239 CAD, which I expected to be translated into USD according to the datetime of the Exit signal. Doing the math yields -239 / 1.32484 = -180.40 USD. However, the value shown is -181.43, so that prompted me to do more investigation.

Using the calculated Profit value and the GrossPips custom metric, I created another metric, called USDtoQuoteRatioAtExit, that is shown with yellow highlight. Interestingly enough, that value is almost identical to the Close price from 1 day prior to the Exit from the trade. Is there something that I'm missing, which shifts some arrays by 1 day? The impact is really small, but I really want to understand the mechanics of backtesting and the price series being used, so any help is appreciated.

Thanks a lot!

AFL for the main code:

SetOption( "FuturesMode"			, True	);
SetOption( "SettlementDelay"		, 0		);

RoundLotSize = 0;

SetOption( "InitialEquity"			, 100000);
//SetOption( "AccountMargin"		, 100	);
SetOption( "MaxOpenPositions"		, 200	);
SetOption( "AllowPositionShrinking"	, True	);
SetOption( "MinShares"				, 0.01	);

SetOption( "CommissionMode"			, 3		); // $ per share or contract
SetOption( "CommissionAmount"		, 0		); // $ commission (per side)
SetOption( "InterestRate"			, 0		);

SetPositionSize( 1, spsShares );



FullFormulaPath = FGetCwd() + "\\" + GetFormulaPath();

SetCustomBacktestProc(StrReplace(FullFormulaPath, ".afl", "-CBT.afl"));



// initialize each of the 4 possible trade signals
Buy      = Sell      = Short      = Cover      = 0;
BuyPrice = SellPrice = ShortPrice = CoverPrice = C;

// actual signals logic, which overrides the above
Buy   = DayOfWeek() == 1; // buy Monday
Sell  = DayOfWeek() == 5; // sell Friday

BuyPrice   = O; // buy at the Open
SellPrice  = C; // sell at the Close

AFL for the CBT code:

bo = GetBacktesterObject();

bo.Backtest(1); // run default backtest procedure

SumGrossPips = 0;
TradesCount  = 0;

for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
{
	sCurrencyBase  = StrLeft ( trade.Symbol, 3 ); // EUR
	sCurrencyQuote = StrRight( trade.Symbol, 3 ); // USD

	iCurrencyBase  = trade.Shares  * trade.PointValue; // 100,000 for 1 "share"
	iCurrencyQuote = iCurrencyBase * trade.EntryPrice; // 120,000 if EURUSD 1.2

	trade.AddCustomMetric( "iCurrencyBase" , iCurrencyBase  );
	trade.AddCustomMetric( "iCurrencyQuote", iCurrencyQuote );



	PtSize = trade.TickSize; // 1 Pt (= 1 Point) = 0.1 Pips
	Digits = IIf( PtSize == 0, 0, Round(Log10(1/PtSize)) );
	trade.AddCustomMetric( "PointSize", PtSize, Digits );

	PriceMove = (trade.ExitPrice - trade.EntryPrice) * IIf(trade.IsLong, 1, -1);

	GrossPips = 0.1 * PriceMove * IIf( PtSize == 0, Null, 1/PtSize );

	trade.AddCustomMetric( "GrossPips", GrossPips, 1 );



	USDtoQuoteRatioAtExit = GrossPips * 10 / trade.GetProfit();
	trade.AddCustomMetric( "USDtoQuoteRatioAtExit", USDtoQuoteRatioAtExit, Digits );



	SumGrossPips += GrossPips;
	TradesCount  ++;
}

bo.AddCustomMetric( "Expectancy Gross Pips", SumGrossPips / TradesCount );

bo.ListTrades();

Here is another picture of the last screenshot, with less columns, so that the main info is easier to read. All four trades are Long 1 contract/lot USDCAD:
USDCAD%2C%20smaller

I found another thread where a fully related issue was discussed (but not solved as of now):

The way FX profit calculation is implemented leads to small differences from what happens in other platforms and a trading account, but at least it's now clear that the root cause for the different PnL is the fact that different values for EntryFxRate and ExitFxRate are being used than the rate when the trade was opened/closed.

See this: http://www.amibroker.com/kb/2006/08/09/amibroker-for-forex/ and use "Detailed log" report mode to find out exchange rate used.

Thank you, Tomasz, I'm still learning, and not know about "Detailed log". Will try that next!