while backtesting, this error has occured:
Error 18.
COM object variable is not initialized or has invalid type (valid COM object handle required).
Amibroker highlighted this part of the code:
@ondra10192, the Component Object Model (COM) is a (somewhat old) Windows technology that defines and implements mechanisms that enable software components, such as applications, data objects, controls, and services, to interact as objects.
The AmiBroker Portfolio Backtester Interface is implemented using this kind of technology, so the errors it reports are labeled as COM errors (and they are raised when your code is doing something wrong, like calling a function with wrong parameters, a number of args less than required, etc.).
Anyway, your pasted code (ignoring the last incomplete line) seems wrong:
@ondra10192 - First you did NOT post entire code. This makes it impossible to answer correctly. Please follow this advice: How to ask a good question
Your trade variable is apparently NEVER defined or assigned. But since you are not posting entire code it is guessing game. And we don't play guessing games here.
I really don't mean to waste anyone's time. Sorry for not posting the entire code before. I appreciate your feedback. The entire CBT part is here:
AddToComposite(ATR(5),"~atar_"+Name(),"C",atcFlagEnableInBacktest);
SetCustomBacktestProc("");
if (Status("action") == actionPortfolio)
{
bo = GetBacktesterObject(); // Get backtester object
bo.PreProcess(); // Do pre-processing
for (i = 0; i < BarCount; i++) // Loop through all bars
{
for (sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
{ // Loop through all signals at this bar
if( sig.IsEntry() )
bo.EnterTrade( i, sig.Symbol, sig.IsLong(), sig.Price, sig.PosSize );
if( sig.IsExit() )
bo.ExitTrade( i, sig.Symbol, sig.Price );
}
bo.HandleStops( i ); // Handle programmed stops at this bar
for (trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos()) //loop through open positions
{
atar = Foreign("~atar_"+sig.symbol(),"C");
if(trade.GetPrice(i,"C") <= trade.EntryPrice-(3*atar[i])); // if price drops under SL, I will exit the trade
bo.ExitTrade(i, sig.Symbol, trade.EntryPrice-(3*atar[i])); //exiting the trade at the SL price
}
bo.UpdateStats( i, 1 ); // Update MAE/MFE stats for bar
bo.UpdateStats( i, 2 ); // Update stats at bar's end
} // End of for loop over bars
bo.PostProcess(); // Do post-processing
}
trade is the variable you're using to loop through open positions.
I think that the problem is that you have no open positions, so trade will never have a value (i.e. it is a variable that will never be initialized).
You can try to call bo.Backtest before bo.GetFirstOpenPos to make Amibroker generate a trade list...
As @beppe wrote - your code has an extra semicolon that TERMINATES if statement, so next line is executed unconditionally: You must REMOVE THAT SEMICOLON!
if(trade.GetPrice(i,"C") <= trade.EntryPrice-(3*atar[i])); // SEMICOLON here is an ERROR
bo.ExitTrade(i, sig.Symbol, trade.EntryPrice-(3*atar[i]));
should be:
if(trade.GetPrice(i,"C") <= trade.EntryPrice-(3*atar[i]))
{ // if price drops under SL, I will exit the trade
bo.ExitTrade(i, sig.Symbol, trade.EntryPrice-(3*atar[i]));
}
Thank you for pointing out the extra semicolon but it doesn't solve the problem.
The code works fine withouth this CBT part. Which should mean that the problem is within this CBT part. The whole point of using this low-level CBT is that I want to use a specific SL (placed at a distance of 3xATR(5) under the entry price). Using ApplyStop function is not possible since it is not supported in backtestRegularRaw mode.
@ondra10192, try replacing the sig.Symbol in this loop with trade.Symbol:
for (trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos()) //loop through open positions
{
atar = Foreign("~atar_"+trade.symbol(),"C");
if(trade.GetPrice(i,"C") <= trade.EntryPrice-(3*atar[i])); // if price drops under SL, I will exit the trade
bo.ExitTrade(i, trade.Symbol, trade.EntryPrice-(3*atar[i])); //exiting the trade at the SL price
}
Hooray!! Thank you @beppe It works. I replaced sig.symbol() with trade.Symbol in the code and its working fine now. I will definitely reread the Reference Guide. This was my first Low-level CBT that I ever created. Feels nice that it actually works
Still this line is simply wrong. Terminating semicolon is still in wrong place
Corrected version:
if(trade.GetPrice(i,"C") <= trade.EntryPrice-(3*atar[i]))
{ // if price drops under SL, I will exit the trade
bo.ExitTrade(i, trade.Symbol, trade.EntryPrice-(3*atar[i]));
}
Yes, you are 100% right. I simply pasted a section of the OP code and modified it as suggested but forgot to remove the extra semicolon (that I also spotted on my first answer). Sorry for the oversight.
Quite frankly if original poster just looked carefully at the error message he got, it was pointing right before his eyes that sig variable is NOT valid (it was zero). And that it is precisely explained in the manual http://www.amibroker.com/guide/errors/18.html and one only needs to press F1 on error message to get the insight.