Intro To Atc
Intro To Atc
~~~
For convenience the AddToComposite() will from here on be referred to with Atc.
The Atc is an extremely powerful function and I strongly encourage you to. This
application will show you the basics as well as introduce you to more sophisticated
applications. For further help in the application of the Atc please post your questions to
the AmiBroker user list, there are many users there willing to help you.
Boxed text contains text copied from AmiBroker Help, AmiBroker Newsletters, and
various web postings. Credit was given where it was readily available but omitted in
other cases for the sake of saving time.
This is not a programming tutorial, and the code segments provided may not be optimum
for what is being accomplished: they are only examples or ideas to get you started with
the AddToComposite.
The trading systems included or referred to should NOT be traded as they are; here again:
they are only examples of how one could go about designing a system.
Thanks goes to Tomasz Janeczko, Dale Wingo and Dimitris Tsokakis for proof reading
this document, for making helpful suggestions, and for providing additional information
to be included.
Page 1 of 1
CONTENTS
Introduction [Next] ......................................................................................................... 3
Calculating multiple-security statistics with the AddToComposite function [Next]...... 4
AmiBroker 4.16 AddToComposite additional flag definitions [Next]........................... 7
Naming Composites [Next] ............................................................................................ 8
Deleting Composites [Next] ........................................................................................... 8
Making the Atc work in all AA Functions [Next] .......................................................... 9
Enabling and Disabling the Atc [Next]........................................................................... 9
Atc Resets [Next].......................................................................................................... 10
Where do the Composites go? [Next]........................................................................... 10
Which Field to use in your Atc? [Next]........................................................................ 10
Copying Composite Files [Next] .................................................................................. 11
Cloning a Security [Next] ............................................................................................. 11
Dynamic naming of Composites [Next] ....................................................................... 12
Counting the number of stocks traded each day [Next]................................................ 12
Calculating Advance/Decline lines [Next] ................................................................... 13
Counting binary Events [Next] ..................................................................................... 14
Qualifying Counts [Next] ............................................................................................. 14
Coping with Volume overflow [Next].......................................................................... 14
Full Sector, Industry or Market Composites [Next] ..................................................... 15
Creating WatchList Composites [Next]........................................................................ 15
Creating Equity Composites when Backtesting [Next] ................................................ 16
Creating individual Equity composites for each stock optimized[Next] ...................... 16
Creating an Equity chart with OHLC price fields [Next] ............................................. 16
Calculate an average Market price [Next] .................................................................... 17
Using the Optimizer as a Task Scheduler [Next].......................................................... 17
Using the Atc to create Static storage space [Next]...................................................... 18
Adding Columns to your Optimizer Reports [Next]..................................................... 19
Using the Atc for Signal-Averaging (Unfinished) [Next] ............................................ 20
Calculating Multiple Security Indicators [Next]........................................................... 21
Stochastic Divergences, PDI, NDI [Next] .................................................................... 22
36 Trading Systems Based on the RSIt [Next] ............................................................. 23
Over-Sold and Over-Bought Indicator [Next] .............................................................. 23
Bull-Bear-Congestive Composites [Next] .................................................................... 24
Composite Bull Pressure and Bear Pressure [Next] ..................................................... 25
Creating Signal Consensus Composites [Next] ............................................................ 26
CCI50 TTM System [Next] .......................................................................................... 27
StoRSI-Bull/Bear Pressure trading system [Next]........................................................ 27
Optimizing Trading Systems for Expectancy [To Index]............................................. 29
A few final references ................................................................................................... 32
Page 2 of 2
Introduction
[Next]
To be a successful trader you have to be able to recognize (or better even: anticipate)
what other traders are doing. After all the Market doesnt move by itself: it is trader
driven. If everybody is buying the price goes up and if everybody is selling the price goes
down.
To know what traders are doing you have to deal with averages; i.e. you need an indicator
to show how many people are selling or buying, what is the average price change in a
sector, how many shares are traded, etc. Some indices may provide this information but
they are rigid; you cannot modify the stock population they are based on. Using the
AmiBroker Atc you can create almost any averaging (based on multiple securities)
indicator you may need.
You can also use it to sum parameters or values from traditional indicators for individual
Stocks or groups of stocks in your Watchlists, or in Sectors, Industries, specific Markets
or even All Markets.
A typical application for the Atc would be to gate or enable your trading signals with
a Composite Bull/Bear Trend indicator. In this case you may decide not to place Long
trades in a Bear Market and/or not to place Short trades in a Bulls Market. This is
sometimes referred to as qualifying your trades or confirming your trades with
secondary signals or indicators.
You can exploit the correlation of individual stocks to composite indicators by designing
a Trade-The-Market (TTM) trading system. Dimitris Tsokakis has made numerous posts
on this topic on the Yahoo AmiBroker user list. Such systems may completely ignore
individual stock price movements and trade a portfolio purely on the basis of signals
derived from overall market movements. This idea is controversial however I suggest you
explore the idea. Several very interesting TTM systems have been discussed on the
AmiBroker mailing list.
For those who enjoy researching the Markets and look for anomalies (great pastime!) the
Atc offers a variety of opportunities. This function is a great tool to sum up events,
patterns, parameters, etc for export and analysis to/in Excel.
It is important to develop a general appreciation of what the Atc can do for you. The best
place to start is the AmiBroker Atc help (Copied below) and the 12/2001 and 04/2000
issue of AmiBroker tips newsletter on the AmiBroker Website.
The 12/2002 newsletter was written before the afl Atc became available. It creates and
explains how to create composites using J- and VB-scripts. Program examples are
By Herman van den Bergen [ [email protected] ]
Last Updated: 2002-11-12
Page 3 of 3
discussed and listings are provided. While the script versions are more complicated they
do provide a different view on the topic and this could be important in some applications.
Page 4 of 4
RETURNS
NOTHING
FUNCTION
Parameters:
array - the array of values to be added to "field" in "ticker" composite
symbol "ticker" - the ticker of composite symbol. It is advised to use
~comp (tilde at the beginning) newly added composites are assigned to
group 253 by default and have "use only local database" feature
switched on for proper operation with external sources
Possible field codes: "C" - close , "O" - open, "H" - high, "L" - low,
"V" - volume, "I" - open interest, "X" - updates all OHLC fields at
once.
Flags - contains the sum of following values 1 - reset values at the
beginning of scan (recommended) 2 - put composite ticker into group
253 and EXCLUDE all other tickers from group 253 (avoids adding
composite to composite) 4 - put last scan date/time stamp into
FullName field.
AddToComposite function also detects the context in which it is run
(it works ONLY in scan mode) and does NOT affect composite ticker
when run in Indicator or Commentary mode, so it is now allowed to
join scan and indicator into single formula.
Page 5 of 5
your index.
Shortly this formula just adds Close price to OHLC fields (the "X" field stands for all
OHLC) of our artificial ticker ~MyIndex. Additionally we add "1" to "I" (open interest)
field - effectivelly counting the number of symbols scanned. We can use symbol count
later on to divide the sum of prices by the number of symbols included ( the last line of
the formula above ).
Example 2:
In the second example we will show how to calculate the indicator that shows the number
of stocks meeting certain criterion. In this example this would be RSI less than 30
(oversold condition), but it can be anything you like.
So the first line of our formula will be:
values = rsi() < 30;
This will store "true" in the values array for all date points when RSI is less than 30. Then
we add regular AddToComposite part:
buy = 0; // do not generate signals
AddToComposite( values, "~MyComposite", "V" );
If we run the formula using "Scan" function of Automatic Analysis window the result
would be an artificial stock "~MyComposite" filled with quotations. The Volume field of
those quotes will contain the number of stocks meeting our criterion (RSI<30) in the
population of scanned stocks.
You can easily see the chart of this new "indicator" using the following custom formula
in Indicator Builder:
graph0 = foreign("~MyComposite", "V");
High values of this "indicator" show that most of the stocks in the analysed group are
oversold. This usually happens before a great rise of the whole market. We just created
market-wide oversold detector!
Example 3:
In the third example I will show you how to use the same technique to count the number
of open positions of your trading system. This is useful if you want to know how big
account would you need to trade your system following all the trades. Our formula will
be very similar to the one before.
By Herman van den Bergen [ [email protected] ]
Last Updated: 2002-11-12
Page 6 of 6
Page 7 of 7
.
AddToComposite has 2 new flags that allow running AddToComposite in
backtest/optimization mode and exploration mode
atcFlagEnableInBacktest = 8
atcFlagEnableInExplore = 16
the following constants were added for readability of formulas using AddToComposite:
atcFlagResetValues = 1
atcFlagCompositeGroup = 2
atcFlagTimeStamp = 4
atcFlagEnableInBacktest = 8
atcFlagEnableInExplore = 16
atcFlagDefaults = atcFlagResetValues | atcFlagCompositeGroup | atcFlagTimeStamp;
Page 8 of 8
Caution is advised since deleted stocks or indices can be a hassle to replace. To remove
many composites it is better to click Symbols -> Organize Assignments -> Groups ->
Group 253 (or your custom assigned name) and use one of two methods:
1) To delete a sequential block of composite files you can use Shift-Select to select a
block of stocks, and then click Delete to delete them all.
2) To delete randomly listed composite files you hold down the CTRL key while clickselecting the composites you want to delete. When all have been selected (Highlighted)
you click the Delete button to delete them all.
Sometimes, when we experiment with code we may mess up things and we may end up
with composite files that do not show in the composite directory (group 253) but that still
remain in the All group and there appears no way to Delete these files. You can correct
this problem by Deleting these composite files from the subfolder in your data directory
named _ (underscore), then delete broker.master file in your data directory, and then reload amibroker. Always make backups before performing making major changes.
While somewhat off-topic I might as well caution you also that you should never remove
stocks from one of your Watchlists by Deleting them from your Workspace: this will
remove them permanently from your database! Only use Symbol -> Organize
Assignments or Symbol -> Erase WatchList(s) to modify your Watchlist contents.
Remember that if your current symbol is a Composite your Atc will not function.
Page 9 of 9
Page 10 of 10
AddToComposite(Data, ~MyComp,X;
You can also use the X designator to read back data from composites created this way:
Plot(Foreign(~MyComp,X),MyComp,1,1);
Volume and open interest fields are "independent". Although you can put your
composites in any of OHLCVI fields the close field is related to high/low fields, and if
you store the values only in close field without changing H/L and try to display
candlesticks out of it - the results will be strange. [Tomasz Janeczko]
Page 11 of 11
Sometimes it is handy to clone a security so that you can make changes to it for testing
purposes. You cannot make changes to external data base securities but composites are
saved in local memory and can be modified and saved with altered values.
AddToComposite(O,"~"+ Name(),"O");
AddToComposite(H,"~"+ Name(),"H");
AddToComposite(L,"~"+ Name(),"L");
AddToComposite(C,"~"+ Name(),"C");
AddToComposite(V,"~"+ Name(),"V");
Buy=Sell=Short=Cover=0;
Filter=1;
Caution: You should Scan this formula on a single stock or you will clone all the stocks
in your group. One application would be to create a dummy stock for testing purposes, its
price arrays could be made up from interesting price periods from a variety of different
stocks or artificial data.
Page 12 of 12
Plot(Foreign("~MyCounter","C"),"MyCounter",4,2);
Buy=Sell=Short=Cover=0;
Filter=1;
If you plot this with you will see a chart depicting the number of stocks traded on each
trading day:
Page 13 of 13
direction. I have run a composite on a universe of some 1300 stocks with the following
code......(snip snip: code and explanation that the Volume composite behaves erratic).
Answer: Divide volume by 1000 or more to avoid overflow of integer volume field
AddToComposite(V/1000,"~Universe" ,"v");
Volume field is stored as an 32 bit integer number which has the range of - 2^31 to 2^31
1 [Tomasz Janeczko]
Page 15 of 15
Page 16 of 16
Page 17 of 17
There may be occasions where you are required to perform two or more successive Scans
to accomplish a task. We touched on this earlier. Another example would be were you are
using the results of an earlier Atc to calculate the data for the next Atc. Using the recently
introduced Atc flags you can do many Scans in one operation by using the Optimizer as a
Backtester (because you are not optimizing now) and simple Task Scheduler:
Task = Optimize("Task",1,1,3,1);
AddToComposite(IIf(Task==1,1,0),"~Count","X", 2+10+(Task==1));
AddToComposite(IIf(Task==2,Close,0),"~SumClose","X", 2+10+(Task==2));
AveClose = Foreign("~SumClose","C")/Foreign("~Count","C");
AddToComposite(IIf(Task==3,AveClose,0), "~AveClose", "X",
2+10+(Task==3));
You have to take care of two things: Control what and when data is added and when the
composite is reset. You can extend this idea to your trading systems to do away with
many different Scans and, if you structure you program correctly, you can now update
your composite as part of your backtest. This way you do not need to keep track of
whether your composites are up-to-date.
Page 18 of 18
To save an array you simply replace Buffer with the array you want to make static (save).
Now all that needs to be done is store your Buffer on disk using the Atc function:
Enable = 8; // Set to 8 when you want to save data, to 0 to disable the Atc
AddToComposite(iif(Enable,Buffer,0), ~MyStaticBuffer,X, 3+Enable);
You should call this function only once or it will reset on each iteration.
To recall the variables you use the Foreign():
Buffer = Foreign("~MyStaticBuffer","C");
Data1 = ValueWhen((Cum(1)==1) AND Enable, Buffer);
Page 19 of 19
You can display the added information with an Exploration, set Range -> n last
quotations = 1 to obtain similar column length as obtained with the optimization.
You can use this method to gather any type of optimization data you want, list it with an
Exploration and copy/export to Excel for further analysis or 3D charting. Who said
AmiBroker Optimizations were limited?
Caution again: you will add as many Composite files to your Workspace as there are
iterations in your Optimization.
// Trading system
StochRsi=EMA((RSI(8)-LLV(RSI(8),8))/(HHV(RSI(8),8)LLV(RSI(8),8)),3)*100;
Buy=Cross(17,StochRsi);Sell=Cross(StochRsi,83);
Short=Cross(StochRsi,83);Cover=Cross(17,StochRsi);
E = Equity(1);
// Signal Averaging
Event = Ref(Buy,-1); // Buy Entry price is the Event to analyze
Para = ROC(Open,1); // We will Signal-Average the Open price
MxSam = 300;
// We will Sample 300 Entries
Width = 10;
// We will Display 10 bars, 5 before and 5 after the Event
DCtr = LastValue(Cum(1))-Width/2;
SamNum = Optimize("SamNum",1,1,MxSam,1); //We collect MxSam Samples
EvNum = Cum(Event);
//We count the Events
Hit = (SamNum==EvNum);
HitLoc = ValueWhen(Hit,Cum(1));
OffSet = DCtr - HitLoc; //Calc offset from Display to the Event
Page 20 of 20
Page 21 of 21
Page 22 of 22
graph1color=6;
TITLE=writeval(LASTVALUE( foreign("~posstochdiv","V")))+
" ISSUES WITH BULLISH STOCHASTIC DIVERGENCE "+
" AND "+writeval(LASTVALUE( foreign("~negstochdiv","V")))+
" ISSUES WITH BEARISH STOCHASTIC DIVERGENCE ";
Page 23 of 23
//Plotting
/*Graph for ~stochdosi and ~stochdobi*/
Graph0 = Foreign("~stochdosi","V");
Graph1=Foreign("~stochdobi","V");
Title=Date()+" : "+"stochd OSI = "+
WriteVal(LastValue( Foreign("~stochdosi","V")))
+", stochd OBI= "+WriteVal(LastValue( Foreign("~stochdobi","V")));
Graph0BarColor=4;
Graph1BarColor=5;
Page 24 of 24
values16 = abs(rs)<=1;
values17=rs>1;
values18=rs<-1;
with
values16 = abs(rs)<=0.75;
values17=rs>0.75;
values18=rs<-0.75;
or even
values16 = abs(rs)<=0.5;
values17=rs>0.5;
values18=rs<-0.5;
for more expressive results.
Page 25 of 25
"+WriteVal(Graph0,1.1)+"% )";
/******End of Composite indicator******/
Page 26 of 26
This works best if you backtest a large number of stocks, for example the N100.
The result is an indicator that ranges from 0-100. It produces a score of 100 if the
system produces an identical signal on exactly the same bar for all stocks. We
might assume that this kind of confirmation is a good sign (also assuming your
trading system is reasonably good). You might be able to turn this into a TTM
system
2) Backtesting several different trading systems on a single stock or a group of
stocks like the N100. Each system would provide its own timing, perhaps derived
from completely different principles. Here too you would be looking for
confirmation.
3) Backtesting several different Trade-The-Market systems and looking for a
consensus between the systems. Same rational as before.
4) Backtesting permutations of the same trading system and creating a consensus
signal indicator. For example you could vary the periods by some rule and
investigate what happens to the distribution of trading signals.
Page 27 of 27
Earlier I mentioned that you can use composite derived indicators to gate trading signals.
Here is a system I posted on the AmiBroker user list (2002-08-12) where I combined
Steve Karnishs StoRSI oscillator system with the BullBearPressure indicator origionated
by Anthony Faragasso and implemented into a DLL by Peter Gialames. You can
substitute a variety of other indicators/systems and get pretty good results:
// Composite Bull/Bear Pressure DLLVersion 1.0.. By Anthony Faragasso
// Credit to Peter Gialames for formula conversion into plugin Dll.
// StoRSI by Steve Karnish
x=afBBTicker();//This Calls the plugin
AddToComposite(BullishPressure,"~NDX100bullishpressure","x");
AddToComposite(BearPressure,"~NDX100bearPressure","x");
bull=Foreign("~NDX100bullishPressure","C");
bear=Foreign("~NDX100bearPressure","C");
Pd = 14; //Optimize("PD",10,2,30,2);
SmBULL = hbT3A(100*bull/(bull+bear),Pd,0.5);
SmBEAR = hbT3A(100*bear/(bull+bear),Pd,0.5);
EnL = SmBull > 50;
EnS = SmBear > 50;
StochRsi=EMA((RSI(8)-LLV(RSI(8),8))/(HHV(RSI(8),8)LLV(RSI(8),8)),3)*100;
Buy=Cross(17,StochRsi) AND EnL;
Sell=Cross(StochRsi,83);
Short=Cross(StochRsi,83) AND EnS;
Cover=Cross(17,StochRsi);
E = Equity(1);
Plot(E,"E", 1,1);
Plot(EnL*10,"EnL",5,1);
Plot(EnS*10,"EnL",4,1);
/*
Page 28 of 28
Page 29 of 29
Page 30 of 30
Winnings = Cum(IIf(LongProfit>0,LongProfit,0) +
IIf(ShortProfit>0,ShortProfit,0));
Losses = Cum(IIf(LongProfit<0,LongProfit,0) +
IIf(ShortProfit<0,ShortProfit,0));
NumWinTrades = Cum(((LongProfit>0) OR (ShortProfit>0)) AND
Status("BarInRange"));
NumLosTrades = Cum(((LongProfit<0) OR (ShortProfit<0)) AND
Status("BarInRange"));
TotalTrades = Cum(dSell OR dCover);
WinningTrades = Cum((LongProfit > 0) OR (ShortProfit >0));
LosingTrades = Cum((shortProfit < 0) OR (LongProfit < 0));
AveWinTrade = Winnings / WinningTrades;
AveLosTrade = Losses / LosingTrades;
PercentWinners = WinningTrades / TotalTrades;
Expectation = ( 1 + AveWinTrade/abs(AveLosTrade)) * PercentWinners - 1;
Ex = LastValue(expectation);
IC = Pd-Pd1+LB-LB1+(Pd2-Pd1)*(LB-LB1);
IC = LastValue(Cum(1)) - IC;
AddToComposite(IIf(Cum(1)== IC,Ex,0),"~Expectation","C",10+OptStart);
AddToComposite(IIf(Cum(1)== IC,Pd,0),"~Expectation","V",10+OptStart);
AddToComposite(IIf(Cum(1)== IC,LB,0),"~Expectation","I",10+OptStart);
AddToComposite(IIf(Cum(1)== IC,LastValue(E),0),"~ExpEquity","X",10+OptStart);
AddColumn(AveWinTrade,"AveWTr",1.2);
AddColumn(AveLosTrade,"AveLTr",1.2);
AddColumn(PercentWinners*100,"%Winners",1.4);
AddColumn(Expectation, "Expectation",1.3);
GraphXSpace = 5;
Filter = Status("LastBarInRange");
Plot(E,"Equity",1,1);
/*
I use two indicators to display the results:
Displaying the Expectancy and Equity curves:
Plot(Foreign("~Expectation","C"),"Expectation",1,1+4);
Plot(Foreign("~Exp-Equity","X"),"Exp-Equity",4,16384 +65536 );
GraphXSpace = 10;
Displaying the parameters being optimized:
By Herman van den Bergen [ [email protected] ]
Last Updated: 2002-11-12
Page 31 of 31
Plot(Foreign("~Expectation","V"),"Expectation-Pd",4,1+4);
Plot(Foreign("~Expectation","I"),"Expectation-LB",6,1+4);
GraphXSpace = 10;
To test for Expectancy you copy the above code to your AA and Indicator formula
windows and run the optimizer. Use any range and stock you like, I suggest you use at
least several years of data. The more trades you have the better the results. The chart is
displayed at the extreme right of the X-axes: be sure to zoom in until you see it. Below is
a typical chart.
Page 32 of 32
There are many more good applications for the Atc I would have liked to include but this
document is getting too long.
A very good example that you should study is The Magic OUT3 [and the STOCHRSI]
posted on the AmiBroker user list by Dimitris Tsokakis. It explains how you can use the
Atc to design Filters that can improve almost any trading system. See posts #20284,
20294, 20297 etc. He explains how to design a Filter that will improve the performance
of almost any trading system.
~~~
Happy Trading,
Herman van den Bergen
[email protected]
Page 33 of 33