Missing buy / Sell arrow on charts

I'm having a problem where Buy or Sell arrows are missing from my charts when I complicate my functions.

In the following ma1 is a simple 200 bar moving average and ma2 is modified to still return a value when the stock has less than 200 bars. My Buy and Sell conditions are the same except one uses ma1 and the other ma2 and I'm filtering where both Buy and Sell are true.

When I run an explore the results show both ma1 and ma2 are the same and Buy and Sell are both true but when I click on the results then switch to the chart tab I'm only getting one arrow.

How do I get both the buy and sell arrow to display?

ma1 = MA( Close, 200 ) ;
ma2 = MA( Close, Min( 200, BarsSince( IsNull( Close ) ) ) ) ;

Buy = ma1 > Close ;
Sell = ma2 > Close  ; 

Filter = Buy AND Sell ;

AddColumn( ma1, "ma1" ) ; 
AddColumn( ma2, "ma2" ) ; 
AddColumn( Buy, "Buy" ) ; 
AddColumn( Sell, "Sell" ) ;




read here Portfolio-level back testing (amibroker.com)


In the AFL I posted I want to have both a Buy and Sell signal on the same bar to demonstrate my problem. The output from a scan or explore has a buy and sell on the same bar but the chart doesn't.

If I change my code so the Buy andSell both use the ma1 variable the chart shows a Buy and Sell arrow on the same bar.


If I change it so either Buy or Sell uses the ma1 variable and the other uses the ma2 variable which is the code I posted I only get one arrow and if I change it so both Buy and Sell use ma2 I don't get any arrows on the chart.

The only time the ma1 and ma1 variables should be different is when the stock code has less than 200 bars of history. ma1 will return blank or null while ma2 will return the Moving Average for the total number of bars that exists.

Another option that works which I might use in my actual system is to have a nested IIf statement

ma3 = IIf( NOT IsNull( MA( Close, 200 ) ), MA( Close, 200 ), 
      IIf( NOT IsNull( MA( Close, 150 ) ), MA( Close, 150 ),   
      IIf( NOT IsNull( MA( Close, 100 ) ), MA( Close, 100 ), 
      IIf( NOT IsNull( MA( Close,  75 ) ), MA( Close,  75 ),  
      IIf( NOT IsNull( MA( Close,  50 ) ), MA( Close,  50 ), 
      IIf( NOT IsNull( MA( Close,  25 ) ), MA( Close,  25 ), MA( Close, 200 ) ) ) ) ) ) )  ;  

I have three variables using Moving Average which will all create Buy / Sell signals when I run a scan or explore but only two display signals on the chart.

Such codes do not make sense.

You need to understand how functions work and that MA from 200 bars is available starting from 200th bar. If you need MA available from very first bar you can use other averages such as AMA. Also be aware that charts use QuickAFL that limits number of bars executed to those that are visible.

Recommended reading:

To get better understanding of what is happening in your code and how functions work, use advice given here: How do I debug my formula?


When a stock has less than 200 bars of history I want the moving average to be based on the total number of bars available.

My code runs without error and the results list from the Explore appear to be correct. In the following code ma1 is a simple MA where the period is a variable and ma2 is my MA. I'm then filtering my results so the bar number matches the simple MA periods and comparing the results.

VarBars = Param( "Bars", 10, 10, 250, 10 ) ;  

ma1 = MA( Close, VarBars ) ; 
ma2 = MA( Close, Min( 200, BarsSince( IsNull( Close ) ) ) ) ;

BarNo = BarsSince( IsNull( Close ) )  ;

Filter = BarNo == VarBars ;

Buy = ma1 > 0 ;
Sell = ma2 > 0 ;

AddColumn( BarNo, "Bar No" ) ; 
AddColumn( ma1, "ma1" ) ;
AddColumn( ma2, "ma2" ) ;
AddColumn( ma1 - ma2, "Delta" ) ;  

On the 10th bar of the first stock MA( Close, 10 ) equals 4.68 and MA( Close, Min( 200, BarsSince( IsNull( Close ) ) ) ) also equals 4.68. Both moving averages give me the same result on every stock and period until I increase the periods in my simple MA above 200 and I'm no longer comparing the same ranges.

Explore gives me the results I want using MA( Close, Min( 200, BarsSince( IsNull( Close ) ) ) ) . When I use the results in a Buy or Sell statement Scan and Explore work. The only problem I have is when looking at the chart it's missing the Buy or Sell arrows.

I looked at AMA and it does return a result from the first bar but they are different to what I'm getting so I need to investigate further but given Scan and Explore works with my current code and I'm only missing arrows on the chart I'm unlikely to change.

I dont understand your code

Min( 200, BarsSince( IsNull( Close ) ) 

It could just return random Close and wont be sequentially progressing in bar counting.

I cant find the post(s) but a popular code which i saw here in the forum is like this:

ma2 = MA( Close, Min( 200, BarIndex() )) ;

IsNull( Close ) is pointless. Close is never NULL (unless you override close array or use TimeFrameCompress/TimeFrameSet).

Also starting MA from range = 1 would produce very very noisy output (because of very few bars included) and likely to generate whipsaw orders that you won't like. It makes a lot of sense to just wait for those 200 bars worth of data.

As I wrote, you could use

smoothed = AMA( Close, 2/(Periods+1) );

to get data from very first bar but at least properly smoothed and not as noisy. AMA is exponential smoother (IIR filter) and obviously different than FIR filter such as MA, but different does not mean worse, just the opposite.

If the barcount is 8,000 and a stock has 20 bars does that not mean the database has 7,980 bars where the close and all other values are NULL?

I've found a solution that fixes my original problem.

If not using 'Pad & Align':

  • Barcount is number of actual bars

If using 'Pad & Align':

  • Barcount is number of reference bars (with max limit according to Database setting)
  • Pre-trading bars are filled with nulls
  • Post-trading bars are filled with the last trading bar's values

We are talking about CHARTS in this thread, don't we? The subject of this thread is "Missing buy / Sell arrow on CHARTS" isn't it?

In charts BarCount never exceeds the number of bars that stock has.

"Pad and align" is an Analysis-only setting and it does NOT affect charts. Obviously when one wants to display Analysis that has any correspondence with what is happening on Charts, Pad and align should be turned OFF.

Also formulas don't need to care about Nulls in the beginning of any array as all AFL functions skip Nulls that appear on the beginning of the array and start calculation from first non-null value and this all happens automagically without user knowing or coding for that.

My code creates Buy and sell signals when I run a Scan or Explore. I wanted to know why they were missing when I looked at the chart.

Your assumptions are incorrect.

Incorrect assumption #1, you wrote:

When I run an explore the results show both ma1 and ma2 are the same and Buy and Sell are both true

That is not true. If they were the same the condition > (greater than) would NOT be true.
So they different. You display only two digits after dot and the comparison is made using full precision (7 significant digits) hence you made assumption that is incorrect because you look at rounded numbers yet comparison is done with full precision.

Incorrect assumption #2

Assumption about Nulls in the close. You should NOT be using

BarsSince( IsNull( Close ) ) )

because Close prices if there is NO Padding, are not-null from beginning. If you are using padding, turn that OFF if you want any correspondence with Analysis.

Incorrect assumption #3:

You assume that you need code to display arrows. You don't. Arrows that correspond to Analysis output are displayed OUT OF THE BOX, without any coding, if you just use right click Analysis menu

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