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