Position Score Issue

I have a formula (removed in the code below) which is used for entry but also for score for portfolio trading of more than 50 stocks.

The score as of 09/19/2018 is include in one pic.

The open positions as of 09/20/2018, one day latter, are included in another pic.

On 09/19/2018 the code issued signals for closing 5 positions at the open of the next day, 09/20/2018

That meant that 5 new positions should be opened since maximum position is 10.

However, the code skipped CL and VZ that had higher score than SO and BMY, as you can see from the open positions.

Any idea why that happened?

Thank you

SetBacktestMode(backtestRegular ); //No multiple positions
SetOption("allowsamebarexit",True);
SetOption("priceboundchecking",True);
np=Optimize("number",5,1, 42,1);
MaxPositions = 2*np;
SetOption("MaxOpenPositions",maxpositions);
SetPositionSize( 100 / MaxPositions, spsPercentOfEquity ); 
SetTradeDelays( 1, 1, 0, 0 );
Myformula = ;//removed, ranges between 0 and 100
Buy = formula < 20;
Short=0; 
Cover=0;
Sell=formula > 80;
BuyPrice=SellPrice=Open;
Score = 100-myformula; 
PositionScore = score;
Filter = Positionscore;
AddColumn(Positionscore, "Score");

score%2020180919 Open%20pos%2020180920

@makhar88, in general, to debug this kind of issue one of the most useful tool is the "Detailed Log": an option that you'll find in the Backtester settings dialog, that you'll open clicking this icon immagine in the Analysis tab.

immagine

3 Likes

Thanks, I know the tool, it did not help. The issue is straight forward. Amibroker skipped two stocks with higher score for unknown to me reasons. Maybe for reasons I do not understand. Debug provided no information about the skipped stocks. None at all.

My experience is that if you actually generate an entry signal (you have provided no evidence that you did, unless formula is the same as MyFormula in your example), then the Detailed Log (not the debugger) will show you the signal and either the entry details or the reason the signal was rejected. Since your top secret formula is too valuable to share with the forum, no one else will be able to reproduce your problem and suggest ways to fix it.

3 Likes

@makhar88 your exploration results (as per posted image), if created with the posted code, does not take into account the Buy condition:

Try to modify it as:

Filter = Buy;
AddColumn(PositionScore, "Score");

PositionScore is used ONLY to rank entries trade signals.

3 Likes

@beppe, thank you, I made the change and results are exactly the same. I repeat the code below with a correction without my formula which I cannot reveal due to restrictions from work:

SetBacktestMode(backtestRegular ); //No multiple positions
SetOption("allowsamebarexit",True);
SetOption("priceboundchecking",True);
np=Optimize("number",5,1, 42,1);
MaxPositions = 2*np;
SetOption("MaxOpenPositions",maxpositions);
SetPositionSize( 100 / MaxPositions, spsPercentOfEquity ); 
SetTradeDelays( 1, 1, 0, 0 );
Myformula = ;//removed, ranges between 0 and 100
Buy = myformula < 20;
Short=0; 
Cover=0;
Sell=myformula > 80;
BuyPrice=SellPrice=Open;
Score = 100-myformula; 
PositionScore = score;
Filter =Buy;
AddColumn(Positionscore, "Score");

The output is exactly the same as in my original post. Two stocks are skipped although they have higher score. There must be something else or some other reason for that.

@mradtke response was actually spot on. And your response to his genuine help was wrong. You should debug your own code yourself as described here: How do I debug my formula? and yes "Detailed log" is where you should be looking at.

1 Like

You are using SetTradeDelays in backtest code but SetTradeDelays is backtester function!
SetTradeDelays will not work the same way in exploration. Exploration is not backtest.

Since you use one bar delay in SettradeDelays

SetTradeDelays( 1, 1, 0, 0 );

you need to add Ref() in Exploration.

delay = 1;
Filter = Ref(Buy, -delay );
AddColumn(Ref(Positionscore, -delay ), "Score");
AddColumn(Ref(Buy, -delay ), "Buy");
3 Likes

He would find that himself if he used "Detailed log".

For debugging backtest one should use "Detailed log" as it comes from the backtester directly and it displays position scores as they are used by the backtester with all delays already applied as backtester does plus TONS of other useful information when for example trades are skipped due to insufficient funds or other constraints. Such information can't be obtained using exploration.

Everything is already given here: How do I debug my formula?
Using this advice saves heaps of time.

1 Like

@mradtke wrote:

"My experience is that if you actually generate an entry signal (you have provided no evidence that you did, "

I have provided pics of signals. This is why I thought his post was not helpful but derogatory.

Debug does not provide any information in my case. I have checked the signals manually and visually by charting the formula. I will also try suggestion by @fxshtrat but I am not sure it helps.

I attach the detailed log. Note the new position in red rectangle. According to score calculated as of close of 09/19/2018, SO and BMY should not be there on 09/20/2018 because the stocks with highest score are:

AIG, CL, CMCSA, VZ, HON

LOG%2020180920

I tried method by @fxshtrat and actually shifts score back one day. The way my strategy works is that score is calculated as of close of the day and then new open positions are entered at the next open.

YOUR SettradeDelays (which is backester function) shifts back Positionscore by one bar too.

If using Ref with one bar delay in exploration then you get same positionscore at same date as it is shown in detailed log.

delay = 1;
SetTradeDelays( delay, delay, delay, delay  );

Buy = Cross(C, MA(C,20)); 
Sell = Cross(MA(C,20), C); 
Short = Cover = 0;

PositionScore = 100 - RSI();

AddColumn( Ref(Buy, -delay ), "Buy", 1);
AddColumn( Ref(Positionscore, -delay ), "Score" );

Filter = Ref(Buy, -delay );

Detailed Log
115
Exploration
41

Detailed Log
06
Exploration
35

etc.

3 Likes

@makhar88: the code that you originally posted and which I responded to included this logic:

Myformula = ;//removed, ranges between 0 and 100
Buy = formula < 20;
...
Score = 100-myformula; 
PositionScore = score;

Since formula and myformula are different, there was no way to tell what values are in the Buy array. Then @beppe also pointed out that you should incorporate the Buy signal into your Exploration output so that you can verify for yourself that the signal is actually set on the bars that you think it is. You could also run a Scan to see the entry and exit signals. And finally @Tomasz has pointed you toward the post on how to debug your formula.

All of us are trying to tell you the same thing: you can't jump to the end of the process (entering the trade) and make any valid conclusions about why it didn't work the way you expected it to. Instead, you need to start at the beginning (assigning the Buy, PositionScore, and PositionSize variables), and confirm that it really worked. If so, then go to the next step (did the Buy signal make it to the back tester as you expected, or did AmiBroker filter it out for some reason) and the next (if the signal made it, what did the back tester do with it?), etc.

1 Like

On a side note:

It is not the first time when a new user (without any significant achievements or history on the forum) tends to tell experienced users with a long history of helping others - in this case @mradtke, how they should behave.

It's a pity there is no easy way of identifying (at first sight) experienced users on the forum without studying forum statisticks or going into other user accout's details - which new users are not aware of and won't do. Maybe if there were some visible achievements below the avatar/profile picture (in a similar way to many other forums) it would make new users take more seriously help offered by the experienced users and think twice before accusing them of some alleged wrongdoings or bad intentions. For instance, when I receive a reply from an experienced user (on some other forums), it always make me rethink my potential reply, because there is high chance that I might be missing something and this user might be right.

That being said, I'm aware of the limitations imposed by the forum software and for this reason it probably can not be implemented by @Tomasz ...

Regards

3 Likes

No, that is incorrect.

Highest ranked symbols that have a BUY signal are AIG, CMCSA, HON, SO, BMY...

Detailed log shows highest ranked symbols (sorted by position score). I marked relevant part on your screenshot:

image

And new positions are opened exactly in that ranked order.

Your misunderstanding comes probably from the fact that you look for scores for every symbol while you should be looking only at position scores of symbols that generated a BUY signal on that particular bar.

Your Filter variable in the original code was wrong:

Filter = Positionscore; // wrong. Filter is supposed to be boolean set to True only on entry bars

@beppe and @fxshrat wrote you to use Buy as a filter, that would make it display only ranking for symbols that have actual Buy signal in exploration.

That is why I always tell people: Use DETAILED LOG. It is WAY easier to debug your backtesting with it than using exploration, as with Detailed log you have all details without needing to write single extra line of code.

1 Like

@Tomasz

No, they are not the highest ranking symbols. I also used fxshrat method and it produced the same scores. I attached copy of scores separately.

I have another example that shows a potential issue. with complete code you can also test. If you need the data I can uploaded somewhere.

The code is as follows:

SetBacktestMode(backtestRegular ); //No multiple positions
SetOption("allowsamebarexit",True);
SetOption("priceboundchecking",True);
SetOption("WorstRankHeld", 0.2);
np=Optimize("number",5,1, 42,1);
MaxPositions = 2*np;
SetOption("MaxOpenPositions",maxpositions);
SetPositionSize( 100 / MaxPositions, spsPercentOfEquity ); 
SetTradeDelays( 1, 1, 0, 0 );
score= RSI(4);
PositionScore = 100-score;
Buy = score < 20;
Short=0; 
Cover=0;
Sell=score > 80;
BuyPrice=SellPrice=Open;
Filter = Buy;
AddColumn(Positionscore, "Score");

As of close of 09/19/2018, there are two symbols with position score > 80: NEE and UPS

But Amibroker takes only NEE and not UPS, and leaves only 9 open positions for 09/20/2018 when it could take 10 with UPS.

So I tried to understand why this happens. I think I do. It probably has to do with fact that UPS theoretically still has an open position although not taken because there were more signals than positions back on 09/14/2018, as shown marked on the attached log.

I will continue my post with the score exploration as of the close of 09/19/2018. . LOG%20RSI4%2020180920

Here is the score explorationscore%20RSI4%2020180919 :

to @mradtke: that was a typo, when I removed the formula, I wrote my formula in one place and formula in another. That does not change the substance of the results I posted.

The results for RSI(4) can be replicated by anyone, if you need the data I use can upload.

To the person that thinks that no posts in the forum means no experience. I have been using Amibroker for two years now and the reason I do not post in the forum is because I prefer to solve my problems myself but this one I could not. You are reaching wrong conclusions from wrong assumptions. I have been in systematic fund management business for 20 years. The issue I posted in this forum was reviewed by two more experienced individuals with the particular strategy before that.

@makhar88: you're pretty combative for someone who's asking for help. Few people on this forum have found that to be an effective strategy.

If you haven't already, I suggest you read this: https://www.amibroker.com/guide/h_portfolio.html. It relates to your observation that there may have been previous entry signals generated for some of your symbols and also ties to my previous advice to:

go to the next step (did the Buy signal make it to the back tester as you expected, or did AmiBroker filter it out for some reason)

5 Likes

I think that "this person who thinks..." is me. You are reaching wrong conclusions. The fact that you have been a fund manager for 20 years doesn't change the fact, that you are new here and should mark your words when responding to users who offer you their advice and share their knowledge for free. They are not paid for it. They are users just like you. They don't have to do that. No one has to.

Demanding from Tomasz to remove someone's post (especially when it turned out to be a good one) and advising a user to go and do something else is rude.

Maybe because @mradtke has received over 400 likes - which is 400 times more than you - over 400 people found his replies useful.

You are very rude - probably because you are a "fund manager with over 20 years of experience" and you look down on regular users helping others on the forum for free..

5 Likes

Nonsense. Exploration code with or without delay do not produce same scores.

If you do this in exploration code as you do

delay = 1;
SetTradeDelays( delay, delay, delay, delay  );

Buy = Cross(C, MA(C,20)); 
Sell = Cross(MA(C,20), C); 
Short = Cover = 0;

PositionScore = 100 - RSI();

AddColumn( Positionscore, "Score" );

Filter = Buy;

Then positionsscore of exploration will differ from detailed log's positionscore.

46

56


You will get exploration date's positionscore matching detailed log's score at entry date only if you do apply same bar shifting via Ref() in exploration code as inserted in Settradedelays for backtest code.

delay = 1;
SetTradeDelays( delay, delay, delay, delay  );

Buy = Cross(C, MA(C,20)); 
Sell = Cross(MA(C,20), C); 
Short = Cover = 0;

PositionScore = 100 - RSI();

AddColumn( Ref(Positionscore, -delay), "Score" );

Filter = Ref(Buy, -delay);

17

56

Pointless thread...

3 Likes