HomeKnowledge Base

How to plot daily High and Low on intraday chart

The AFL offers a set of time-frame functions which allow to use multiple intervals within a single formula (the topic is explained in details in the following tutorial chapter:

In situations, where we do not need to calculate any indicators based on higher interval data, but rather just read OHLC, V or OI arrays – TimeFrameGetPrice is the most convenient function to use.

To plot daily High and Low levels we just need to read the respective arrays calling: TimeFrameGetPrice(“H”, inDaily ) – the first argument specifies the array we want to read, the second argument defines the interval we are reading data from. As with any other TimeFrame functions – we can only read data from higher intervals, so it is possible to read daily data when we work with 1-minute quotes, but not the other way round.

Here is a sample formula which draws daily high and low in the intraday chart:

PlotClose"Close"colorDefaultstyleBar );
PlotTimeFrameGetPrice("H"inDaily ), "day high"colorGreenstyleStaircase styleThick);
PlotTimeFrameGetPrice("L"inDaily ), "day low"colorRedstyleStaircase styleThick); 

TimeFrameGetPrice() functions allow also to easily shift the reading by N-bars of the higher interval if we specify that in 3rd argument of the function, so calling TimeFrameGetPrice( “H”, inDaily, -1 ) will return the high of previous day.

The following code draws high / low of previous day on top of the intraday chart:

PlotClose"Close"colorDefaultstyleBar );
hlstyle styleStaircase styleThick;
PlotTimeFrameGetPrice"H"inDaily, -), "Prev High"colorGreenhlstyle );
PlotTimeFrameGetPrice"L"inDaily, -), "Prev Low"colorRedhlstyle ); 

Daily H-L

How to adjust the number of blank bars in right margin

The default number of bars shown in the right-hand side of the chart area is defined in Tools->Preferences->Charting:

Blank bars

It is also possible to extend the blank bars area manually. Pressing END key on the keyboard will add 10 extra bars with each keystroke. Pressing HOME will reset the blank bars area back to default value from Preferences.

Number of bank bars can also be controlled using SetChartOptions() function from the code.

SetChartOptions00chartGridMiddle00100 );
PlotClose"Close"colorDefaultstyleBar );

Detailed documentation of SetChartOptions function is available in the manual:

Indicators based on user values rather than standard OHLC prices

Sometimes we may want to calculate indicators based not only on standard OHLC prices but on some other user-definable values. Some functions like RSI or CSI have additional versions (RSIa, CCIa respectively) that accept custom input array. In this case it is very easy to calculate the indicator based on user defined value. For example RSI from average of High and Low prices could be written as follows:

customArray = ( High Low ) / 2;

PlotRSIacustomArray14 ), "RSI from (H+L)/2"colorRed );

But many of the built-in indicators available in AFL as functions refer indirectly to standard OHLC arrays and their parameters do not offer array argument as one of inputs.

Fortunatelly there is an easy way to provide custom array as input for any other built-in functions. For this purpose, it is enough to override OHLC arrays (or just Close if the indicator only uses Close as input) within the code before calling given function and assign our custom array. As a simple example, let us consider calculating MACD indicator out of average of High and Low prices as input.

procedure SaveRestorePricesDoSave )
DoSave )
SaveO Open;
SaveH High;
SaveL Low;
SaveC Close;
SaveV Volume;
Open SaveO;
High SaveH;
Low SaveL;
Close SaveC;
Volume SaveV;

// save OHLCV arrays
SaveRestorePricesTrue );

// calculate our array
customArray = ( High Low ) / 2;

// override built-in array(s)
Close customArray;

// calculate our function, MACD and Signal in this case
PlotMACD1226 ), "MACD"colorRed );
PlotSignal1226), "Signal"colorBlue );

// restore OHLCV arrays
SaveRestorePricesFalse );

The code first calculates the custom array (we use just use average of High and Low prices in this example, but of course the calculations may be more complex), then assigns the result of these calculations to Close overriding the regular values stored in close array. Then – when we call MACD() function which uses Close as input – it will be based on the modified values.

The above operations do not affect the underlying database at all – the prices are overridden only for the purpose of calculation of this particular formula and other charts / indicators are not affected at all.

How to sync a chart with the Analysis window

When we want to sync a chart with the selected symbol in the Analysis results list, it is enough just to double-click on the particular line in the list and AmiBroker will automatically switch the selected symbol and interval to match the Analysis window.

Sync by double click

Additionally, when we browse through Scan or Backtest results, double-clicking would be an equivalent of Show arrows for all raw signals option from the context menu and would display trading arrows in the chart to match the signals generated by the formula.

If we find that double-clicking is too much work, it is possible to mark Sync chart on select option in Analysis window settings menu:

Sync chart on select

and then single click to select a chart is enough to sync the symbol in the chart. This also allows to use keyboard (up/down cursor keys) to change the selection and sync automatically.

When we have more than one chart window displayed, then Analysis window will always sync the last opened chart window.

If we want to sync multiple chart windows we can use Symbol Link feature. Once multiple windows have the same “Symbol Link” color selected, browsing through the results list in Analysis automatically will automatically sync all linked chart windows (e.g. for the purpose of showing different intervals in each of the charts).


More information about chart link functionality is available in tutorials at: See also video tutorial showing how to use symbol linking:

Using per-symbol parameter values in charts

Parameter values in AmiBroker are stored separately for each ChartID. A ChartID is a number that uniquely identifies chart. This makes it possible that parameters having same name can hold different values when they are used in different charts (different ChartIDs). This also allows to share parameters if two panes use same ChartID. (A detailed explanation can be found here: )

For this reason, if we want to have separate chart parameters for each symbol, we need to set up separate chart for every symbol. To do so, follow these steps:

  1. create several new chart windows using File->New->Blank Chart (or choosing New Blank Chart from the menu under + button in MDI tabs area)
    New Blank Chart

  2. drag Price( all in one) formula or any other indicators onto each of the newly opened windows
    Drag-drop chart

  3. select different active symbol for every chart
  4. define parameters individually and save the whole layout in the Layouts window

As a result – we have a setup of several chart windows, where we can quickly access given symbol showing chart with its separately stored parameters.

MDI Charts

There is also a way to handle the chart parameter values directly from the AFL formula, which would detect the active symbol and set the parameter values accordingly. Here is an example of such implementation using switch statement:

To display this chart, open the Formula Editor, enter the following code and then press Apply Indicator button.

// detect the active symbol and store in n variable

// set parameter values based on the symbol name
switch ( )
// values for MSFT symbol
case "MSFT":
MA1periods 10;
MA2periods 21;

// values for IBM and NVDA
case "IBM":
MA1periods 30;
MA2periods 40;

// values for other tickers
MA1periods 50;
MA2periods 100;

PlotClose"C"colorDefaultstyleBar );

PlotMACloseMA1periods ) , "MA(" MA1Periods ")" colorRed );
PlotMACloseMA2periods ) , "MA(" MA2Periods ")"colorBlue );

This way we can handle all individual parameter values within a single chart pane.

How to force Line chart style for specific symbols (like mutual funds)

There is an easy way to avoid switching the price chart style back and forth if we want e.g. to display a candlestick chart for our stock symbols, but a line chart for just a subset of tickers in our database (e.g. mutual funds).

To achieve that – we need to set Continuous Quotations option to No in Symbol->Information window for the symbols that have only one price fixing per day (only close price available).

Continuous Quotations

Then – if we choose View->Price Chart Style to Auto – the chart will automatically use Line style for all symbols that have Continuous quotations option set to No. Other symbols will still use Candlesticks chart style.

Automatic style

How to export chart image to a file

Charts can be exported as GIF or PNG files either manually or programmatically.

To export chart image manually, simply use Edit->Image->Export to file menu. Instead of exporting you can also copy the image to Windows clipboard (Edit->Image->Copy As Bitmap – this will copy bitmap image or Edit->Image->Copy As Metafile – this will copy vector/scalable graphic).

In order to export image in programmatic manner (from external program), you can use OLE automation interface described here

Below is a sample JScript code that shows how to use OLE interface from the script:

AB = new ActiveXObject("Broker.Application");
AW AB.ActiveWindow;
AW.ExportImage"C:\\example.gif"640480 ); // 640, 480 are pixel dimensions

The code is intended to be used from the outside of AmiBroker.

To use above code follow these steps:

  1. Open Notepad
  2. Copy-paste above the code
  3. Save the file with .JS extension (which means that system will treat this as JScript code)
  4. Make sure that AmiBroker is running with desired chart as active one
  5. Double click on .JS file to execute the JScript code

After doing so, resulting example.gif image file can be found on C: drive.

OLE automation can also be used from any other COM/OLE-aware programs/languages.

Time compression of data retrieved from another symbol

AmiBroker’s Time-Frame functions ( allow to use multiple intervals within a single formula and combine them together. Another set of functions in AFL (Foreign and SetForeign) allow us to retrieve data of another symbol from the database, so we can implement strategies where rules are based on multiple symbols.

This article shows how to combine these two features together and properly use Time-Frame functions on data retrieved from another symbol. Let us consider an example of a strategy, which works on daily data, but uses an additional filter based on weekly readings of S&P500 index.

The following sequence is required to code such conditions properly:

  1. switch to the other symbol with SetForeign
  2. compress data into higher interval with TimeFrameSet
  3. store the weekly values / conditions in custom variables
  4. with TimeFrameRestore() or RestorePriceArrays() functions restore the original arrays of the tested symbol (in the original time-frame)
  5. use custom variables assigned in step (3) expanded to original time-frame using TimeFrameExpand()

Here is the AFL formula, which implements the above conditions:

// first switch to ^GSPC symbol
SetForeign"^GSPC" );
// compress data to weekly interval
TimeFrameSetinWeekly );
// assign weekly values to custom variables
indexWeeklyClose Close;
indexWeeklyMA =  MAClose52 );
indexWeeklyFilter Close MAClose52 );
// restore original arrays (back to the primary symbol)
// RestorePriceArrays() function is an equivalent
// align data back to original interval
indexFilterExpanded TimeFrameExpandindexWeeklyFilterinWeekly );
// exploration shows the results, note that all weekly values
// need to be expanded if we haven't done it yet
Filter 1;
AddColumnClose"Close AAPL" );
AddColumnTimeFrameExpandindexWeeklyCloseinWeekly ), "Weekly close ^GSPC" );
AddColumnTimeFrameExpandindexWeeklyMAinWeekly ), "Weekly MA ^GSPC" );
AddColumnindexFilterExpanded"Weekly index filter");

Let us compare the readings obtained from the code with a sample chart – both ^GSPC raw reading and 52-week MA values match the chart and the condition is properly aligned to the bars starting on 2011-10-28 and extends until new weekly bar is formed.

TimeFrame + Foreign

There is also an alternative method we can use:

  1. retrieve values from ^GSPC using Foreign() function
  2. compress these readings into weekly interval using TimeFrameCompress
  3. perform calculations on weekly compressed array
  4. expand the compressed data back to the original timeframe using timeFrameExpand
indexClose Foreign("^GSPC","C");
indexWeeklyClose2 TimeFrameCompressindexCloseinWeekly );
indexWeeklyMA2 MAindexWeeklyClose252 );
indexWeeklyFilter2 indexWeeklyClose2 indexWeeklyMA2;
Filter 1;
AddColumnClose"Close AAPL" );
AddColumnTimeFrameExpandindexWeeklyClose2inWeekly ), "Weekly close ^GSPC" );
AddColumnTimeFrameExpandindexWeeklyMA2inWeekly ), "Weekly MA ^GSPC" );
AddColumnTimeFrameExpandindexWeeklyFilter2inWeekly ), "Weekly index filter");

How to draw regression channel programatically

Built-in drawing tool allows to place regression channel on the chart manually and the study works on regular Close array as input. The power of AFL allows to automate this task and draw a customizable regression channel automatically in the chart or choose any custom array for calculation.

Here is a sample coding solution showing how to code Standard Deviation based channel. The Parameters dialog allows to control the array the channel is based upon, number of periods used for calculation, position and width of the channel.

lookback Param"Look back"201200);
shift Param"Shift"0020);
multiplier Param"Width"10.2550.25 );
color ParamColor"Color"colorRed );
style ParamStyle"Style"styleLine styleDots );
pricestyle ParamStyle"Price style"styleBar styleThickmaskPrice );
// price chart
PlotClose"Close"colorDefaultpricestyle );
array = ParamField"Price field", -);
BarIndex() + 1;
lastx LastValue) - shift;
// compute linear regression coefficients
aa LastValueRefLinRegIntercept( array, lookback ), -shift ) );
bb LastValueRefLinRegSlope( array, lookback ), -shift ) );
// the equation for straight line
Aa bb * ( - ( Lastx lookback ) );
width LastValueRefStDev( array, lookback ), -shift ) );
drawit > ( lastx lookback ) AND BarIndex() < Lastx;
// draw regression line...
PlotIIfdrawityNull ), "LinReg"colorstyle );
// ... and channel
PlotIIfdrawitwidth*multiplier Null ), "LinReg UP"colorstyle );
PlotIIfdrawitwidth*multiplier Null ), "LinReg DN"colorstyle );

Here is the picture that shows how it looks:

Regression in AFL

Relationship between chart panes

In order to explain possible relationships between chart panes in AmiBroker, let us first introduce two important attributes associated with each chart pane, these are Chart ID and File path.

To see these attributes, we need to right-click on the chart and choose Parameters, then Axes&Grid tab:

Parameters window

The File path defines physical AFL file on your hard-drive that contains the indicator code used to generate charts. The Chart ID is an index to AmiBroker’s internal chart table. The chart table holds chart settings such as those seen in Axes&Grid tab, including the File path. So knowing the Chart ID, AmiBroker knows everything about the chart. The Chart ID uniquely identifies the chart.

Chart ID plays important role in the following areas:

  1. Chart parameters are keyed by Chart ID so two different charts may have same names of parameters, yet parameters are independent if those charts have different ChartID.
  2. Hand-drawn studies are stored wih Chart ID assigned to it, so they “belong” to given chart and can be referenced from other formulas using Study() function
  3. Chart IDs are stored in the layout files so AmiBroker knows which charts should be loaded when layout is loaded.

When we compare two charts, then the following relations are possible:

  1. if both Chart IDs and File paths are different, then charts are completely independent. This will happen if we use Insert option from the Charts window to create a new chart pane or when we double-click on the given formula (double-click works as Insert), because AmiBroker then would create new Chart ID and independent copy of the formula as described in manual


  2. if Chart IDs are different in both chart panes but File Path is the same, then these are different charts, yet they share same formula file. In such case hand-drawn studies will not get transferred and parameters will not be shared, but drag&drop operations and changes in the formula will affect both charts. This situation will occur if we use Insert Linked option from the Charts window to create a new chart pane directly linked to the original formula.

    Insert linked

  3. if Chart ID is the same for both – then it is essentially the very same chart. It means that all the hand-drawn studies and parameters are common for both charts (changes in one chart pane will affect the other) and all the drag&drop operations or formula changes affect both charts – that is because as a result of dragging and dropping indicators the underlying code is being modified (new sections are added). Such relationship between chart panes will happen when we open another chart window that uses the same chart template as the previous window (e.g. using File->New->Default Chart) or save chart template and load it from the other window.

There is also a functionality in AmiBroker, which allows to copy-paste the selected chart pane and define which elements are pasted. To do that click on the pane you want to copy, choose Edit->Copy from the menu, then switch to the place where you want to paste it and choose Edit->Paste Special

Paste Special

Choosing first option creates new Chart ID, and creates a copy of formula, so resulted chart is independent from source chart. Choosing second option creates new Chart ID, but links it to same formula as original, so the formula is shared. Choosing third option inserts a pane that uses same Chart ID (identical chart, everything shared).

Paste Special window

« Previous PageNext Page »