Date to bar to begin plot

I want to plot any indicator, eg 5 period trailing high/low, simple moving average, whatever, for a fixed number of price bars, beginning at a date I input into a Param field, and plotting until the counter = the number I also input in param.

Basically this is to be a barchart of candlestick version of the classic point & figure top or bottom pattern width count, but by counting price bars on a barchart. So if a head & shoulders is 100 bars wide, I want to plot the indicator for 100 days from the breakout date/price bar to visualise when the reversal's effects fade away.

This seemed a simple AFL to attempt but I've got absolutely nowhere and everything I attempt with barcounts, dates, bar numbers fails completely. There's something fundamental I understand completely wrong with these bar-to-date concepts and I don't know what it is.

Can some kind person drop me a hint as to how to get this started?

An example of one failed try:

// Parameters for user input
_SECTION_BEGIN("Range SMA");

P = ParamField("Price field",-1);

startDateYMD = Param("Start Date (YYYYMMDD)", 20250101, 19000101, 21000101, 1);
barLength = Param("Number of Bars to Plot", 10, 1, 500, 1);
smaPeriod = Param("SMA Period", 10, 1, 200, 1);
smaColor = ParamColor("SMA Color", colorRed);
_SECTION_END();

// Convert YYYYMMDD to the format AmiBroker uses internally
startDate = DateNum(startDateYMD);

// Find the bar number for the start date
startBar = LastValue(Cum(1)) - BarsSince(DateTime() >= startDate);

// Create an array with values only in your target range
targetArray = IIf(BarIndex() >= startBar AND BarIndex() < startBar + barLength, Close, Null);

// Calculate SMA just for the specified range
rangedSMA = MA(targetArray, smaPeriod);

// Plot the result
Plot(Close, "Price", colorBlack);
Plot(rangedSMA, "Range SMA", smaColor, styleLine|styleThick);

// Add annotation to show parameters being used
if(Status("action") == actionIndicator)
{
    Title = StrFormat("Range SMA (%g) from %g for %g bars", smaPeriod, startDateYMD, barLength);
}

Here is the way I would probably do this.
The default returned by ParamDate() is the Amibroker DateNum format and I use that. It enforces valid date entry.
Note the correct way to use the DateNum() function.

// Parameters for user input
_SECTION_BEGIN( "Range SMA" );
P = ParamField( "Price field", -1 );
startDateNum = ParamDate( "Start Date_", "2025-01-01" );
barLength = Param( "Number of Bars to Plot", 10, 1, 500, 1 );
smaPeriod = Param( "SMA Period", 10, 1, 200, 1 );
smaColor = ParamColor( "SMA Color", colorRed );
_SECTION_END();

// Create an array with values only in your target range
targetArrayFromStart = DateNum() >= startDateNum;
targetArrayToEnd = BarsSince( targetArrayFromStart == 0 ) <= barLength;
targetArrayMask = targetArrayFromStart AND targetArrayToEnd;

// Calculate normal SMA but only display for the specified range
rangedSMA = IIf( targetArrayMask, MA( P, smaPeriod ), Null );

// Plot the result
Plot( Close, "Price", colorBlack );
Plot( rangedSMA, "Range SMA", smaColor, styleLine | styleThick );

// Add annotation to show parameters being used
if( Status( "action" ) == actionIndicator )
{
    Title = StrFormat( "Range SMA (%g) from %s for %g bars", smaPeriod, DateTimeToStr( DateTimeConvert( 2, startDateNum ), 1 ), barLength );
}
1 Like