PositionSize based on a foreign array during backest

How is it possible to PositionSize using a foreign array during backest? PositionSize must be a number and foreign is an array. How do I get the close value of the foreign array into PositionSize. Any idea?

The most efficient way is to store the array into a static variable before calling the CBT.
In the CBT you read the element [i] of the array, which is a number.

https://forum.amibroker.com/t/need-to-reference-amibroker-price-array-inside-backtester/20454

and

https://forum.amibroker.com/t/how-can-i-access-the-close-price-from-bo-entertrade/23457/4

First: always give ORIGINAL SOURCE of information. Knowledge Base is authoritative source of accurate information. Forum posts may be inaccurate. If something is in the Knowledge base it should used.

Original source of information for passing arrays from first to second phase of backtest is here:

Secondly, Position Size does not need to (and should not) be passed using static variables. And it does NOT need to (and should NOT) be accessed using Foreign.

PositionSize referring to each and every entry signal is already available and direcly accessible in Signal object. So Read the manual, EVERYTHING is explained there. There is even code example.

Quote from the manual
http://www.amibroker.com/guide/a_custombacktest.html

Signal object

[...]
float PosSize
requested position size (positive numbers mean dollar value, negative values mean percent of portfolio equity)

// retrieve the interface to portfolio backtester
bo = GetBacktesterObject();

for( i = 0; i < BarCount; i++ )
{
    for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
    {
       if( sig.IsEntry() )
       {
          // handle entry signal
         sig.PosSize;   // HERE IS YOUR POSITION SIZE FOR GIVEN SIGNAL
       } 
    }
   
    bo.ProcessTradeSignals( i );
}

So, over and over again: READ THE MANUAL. Several times. It is ocean of knowledge that you can jump into and have ALL your problems solved.

The idea of using Foreign is flawed. Don't use Foreign in custom backtest. You should fill PositionSize variable with the data you want to use, not something else. Use existing mechanisms instead of trying to reverse the river with a stick. Learn to use everything the way it was designed, not the "reverse" way.

Last but not least, the original post is flawed because it does NOT EXPLAIN GOAL you want to achieve. You are focusing on flawed "solution" instead of asking HOW to achieve the GOAL and present the GOAL instead of focusing on incorrect details.
Please follow this advice: How to ask a good question

2 Likes

Thank you for the answer. I am not very familiar with CBT but trying to catch up. So, let's say if I'd like to modify the positionsize with a symbol close price (e.g. MSFT) how do you recommend to call it. I copy the code you pasted above (thank you for that) and modify this row to
sig.PosSize=foreign("MSFT","C"); ?

No, you do that in the normal code (not custom backtest). You can assign ANY value to position size directly without using custom backtest.

PositionSize = ....whatever you want...

It can be anything including Foreign although I don't understand why you would use symbol close price as position size. If you want to buy just one share, you should be using 1 share specification, instead of using close price (as price alone is not accounting for commissions):

SetPositionSize( 1, spsShares ); 

Again you are NOT describing the GOAL. ALWAYS describe the GOAL like "I want to buy just 1 share", instead of guessing code.
It is the same as you go to your doctor and you tell the doctor the symptoms or the goal (say "I want to lose weight"), you don't tell him the medicine you want to use, because the medicine that you imagined may not be the cure for the disease or the right solution to achieve the goal.

Thank you, Tomasz. Sorry for not specifying the goal. Here it is.
I've created and imported an array to Amibroker FFF that contains positive and negative values. I'd like to use its value on the day of the entry signal for backtest.
The formula below gives unhandled exception error, probably because PSDenom is an array.

MyArray=Foreign("FFF", "C",fixup = 1);
IIf(MyArray<-2,PSDenom=-MyArray*1.5,PSDenom=3);
PositionSize = 10000/PSDenom;

However, the formula below runs but gives weird results.

IIf(MyArray>-2,PSDenom=3,PSDenom=-MyArray*1.5);

How do you recommend to get the value of the FFF array for PositionSize on the day of the entry signal?

Your code is incorrect and problem is unrelated to PositionSize. The reason is incorrect usage of IIF() function. You are making basic mistake described in the Users Manual:

http://www.amibroker.com/guide/a_mistakes.html#IIF

You have to read that carefully.

This is wrong:

// WRONG WRONG WRONG
IIf(MyArray>-2,PSDenom=3,PSDenom=-MyArray*1.5); 

IIF is a FUNCTION and to make the assignment you have to use the RESULT of it.
You should write

 // CORRECT usage of IIF() - you assign the RESULT of the function
PSDenom = IIF( MyArray > -2, 3, -MyArray * 1.5 );

As to Foreign where exactly do you use that? Send ENTIRE formula not just the fragment.

1 Like

Oh, no. Sorry, I forgot this. This happens when I stop coding for a period of time. Thank you for that.
I use foreign here only, this is the entire formula.
It almost works, there is one problem left. I'd like to set fixup=0 in the foreign and handle the missing array elements but this formula doesn't work.

MyArray=Foreign("FFF", "C",fixup = 0);
PSDenom = IIF( MyArray > -2 OR IsNull(MyArray), 3, -MyArray * 1.5 );
PositionSize = 10000/PSDenom;

How do I handle the missing data on the day of the entry signal? IsNull doesn't seem to work.

As I wrote, use tools to understand your own code - use advice given here: How do I debug my formula?

Using the tools is thousands of times better than expecting others to fix, because if you debug yourself, you will learn something and not make mistakes in the future. Relying on somebody's else would never make you understand your own coding.

Null has special semantics. Any expression having Null is automatically equal NULL. See Null propagates through expressions.

Your statement MyArray > 2 when MyArray is Null is equal to Null. You would find it if you used Exploration to display ( MyArray > -2 ) expression value or used debugger.

You should rather write

PSDenom = IIF( Nz(MyArray) > -2 OR IsNull(MyArray), 3, -MyArray * 1.5 );
1 Like

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.