Ensign Windows has a powerful programming language called ESPL. This Delphi (Pascal) like language can be used to implement proprietary studies, draw tools, alerts, reports, and program control. This article will demonstrate using ESPL to develop a trading system and back test its performance. Consult the Ensign web site for information about ESPL and for the ESPL programming manual.
Our trading system must be kept simple for the sake of being a teaching example. Yet, it will demonstrate many of the design principles that would be used in designing any trading system and back testing its performance. Let's begin by outlining the characteristics of the example trading system.
- It must trade in the direction of the trend. Trade 'short' in a downtrend and 'long' in an uptrend.
- It must have specific, mathematical rules that define the 'signals' for buying, selling, and exiting a position.
- Parameters should be flexible so that different settings can be tried and tested.
- The profitability of the trading system needs to be measured and reported.
The structure of the ESPL program will be like this. Each section will be developed, and then the program will be shown in its entirety.
{define global variables}
{define procedures and functions}
{main program} begin Initialize; Calculate; Report; end;
Initialize The Initialize procedure will be where variables are initialized prior to calculating the trades and accumulating the results for the report. ESPL has the ability to trade our trades and generate a report. The ResetTrades statement is used to define specific Trading System values. The statement is used in conjunction with the Trade, and TradeReport commands. ResetTrades is used to initialize a Trading System. The statement prepares a file to receive the Buy and Sell trades specified by the Trade command. The Commission per contract or per share is specified. The style of the Arrows (marking the trades on a chart) is also specified.
procedure Initialize; var Commission: real; BuyArrow: integer; SellArrow: integer; OutArrow: integer; ShowBoxes: boolean;
begin Commission:=10; {deduct $10 round trip for each trade} BuyArrow:=8; {show Up arrow and the word 'Long'} SellArrow:=13; {show Down arrow and the word 'Short'} OutArrow:=7; {show Right arrow and the word 'Out'} ShowBoxes:=true; {mark trade with a square box on the bar} ResetTrades(Commission,BuyArrow,SellArrow,OutArrow,ShowBoxes);
Position:=0; {0 = out, -1 = short, 1 = long} ScalpSize:=100; {scalp objective, IQFeed users enter 1.00} StopSize:=250; {protective stop, IQFeed users enter 2.50} BuySignal:=false; {flag to indicate Buy setup} SellSignal:=false; {flag to indicate Sell setup} end;
Calculate The Calculate procedure will find the chart, clear it of all studies and markers, put on the Parabolic stop, and loop through all bars in the chart file and make trades based on the rules for the Buy and Sell signals.
procedure Calculate; var w: integer; study: integer; stop: integer;
begin FindWindow(eChart); {locate the window with the chart} Remove(eAll); {clear off studies and markers} study:=AddStudy(ePar); {put on Parabolic stop for trend}
for w:=1 to BarEnd do begin {calculate across all chart bars} stop:=GetStudy(study,3,w); {read the Parabolic position flag} if stop>0 then begin {determine trend} TrendUp:=(stop=1); TrendDn:=(stop=2); HH:=High(w); {start new swing high search} LL:=Low(w); {start new swing low search} end; TestExit(w); {did this bar trigger an exit} TestTrade(w); {did this bar trigger a trade} end; end;
Report The Report procedure will close out the current position, and print a report in the Output window on the ESPL editor form.
procedure Report; begin Trade(eOut); {close-out the last open trade} TradeReport(True); {print the results in the output window} end;
Exit Rules For this simple trade system, a position will be exited when it has hit the protective stop or when it has achieved the scalp objective.
procedure TestExit(w: integer); var bExit: boolean;
begin bExit:=false; if Position=1 then begin {currently long} if Low(w)<=ExitStop then begin {test for stopped out} if Open(w)<ExitStop then ExitPrice:=Open(w) {check for gap across stop} else ExitPrice:=ExitStop; bExit:=true; {set exit flag} end else if High(w)>ExitPrice then begin {test for scalp objective} if Open(w)>ExitPrice then ExitPrice:=Open(w); {check for gap across goal} bExit:=true; {set exit flag} end; end else if Position=-1 then begin {currently short} if High(w)>=ExitStop then begin {test for stopped out} if Open(w)>ExitStop then ExitPrice:=Open(w) {check for gap across stop} else ExitPrice:=ExitStop; bExit:=true; {set exit flag} end else if Low(w)<ExitPrice then begin {test for scalp objective} if Open(w)<ExitPrice then ExitPrice:=Open(w); {check for gap across goal} bExit:=true; {set exit flag} end; end;
if bExit then begin Trade(eOut,w,ExitPrice,1); {exit the position} Position:=0; {position goes to neutral} BuySignal:=false; {clear any pending signals} SellSignal:=false; HH:=High(w); {start new swing high search} LL:=Low(w); {start new swing low search} end; end;
Signal Logic This trading system will watch for higher highs and lower lows to determine swing points. The Parabolic stop will be used to determine the trend. When in an up trend, the signal will be a bar whose High is lower than the swing high. When in a downtrend, the signal will be a bar whose Low is above the swing low. Execution will use the Open of the bar following the signal bar. The Exit Price objective will be the entry price plus a scalp size. The protective stop price will be the entry price minus the stop size. The scalp size and the stop size were variables set in the Initialize procedure and can be adjusted to test the profitability of different settings.
procedure TestTrade(w: integer); begin if Position=0 then begin {do not trade if already in a position} if TrendUp then begin {consider 'long' trade} if BuySignal then begin {did prior bar give buy signal} EntryPrice:=Open(w); {trade at open price} Trade(eBuy,w,EntryPrice,1); ExitPrice:=EntryPrice+ScalpSize; {set scalp objective} ExitStop:=EntryPrice-StopSize; {set protective stop} Position:=1; {new position long} end; if High(w)>HH then HH:=High(w); {find swing high} BuySignal:=(High(w)<HH); {signal is 1st bar below swing high} end;
if TrendDn then begin {consider 'short' trade} if SellSignal then begin {did prior bar give sell signal} EntryPrice:=Open(w); {trade at open price} Trade(eSell,w,EntryPrice,1); ExitPrice:=EntryPrice-ScalpSize; {set scalp objective} ExitStop:=EntryPrice+StopSize; {set protective stop} Position:=-1; {new position short} end; if Low(w)<LL then LL:=Low(w); {find swing low} SellSignal:=(Low(w)>LL); {signal is 1st bar above swing low} end; end; end;
Full Program Cut and the text from this newsletter and paste it into the ESPL editor form in Ensign Windows, or use the Internet Services form to download the script file from the Ensign web site. Open a chart, such as 3-min ES #F, and apply the Parabolic Stop study. For my tests, I have reduced the Acceleration rate and Maximum limit on the Parabolic parameters so the study indicates the bigger trends and has less whip lash. The Parabolic Stop will be used as the indicator for the trend. The trading system only takes Long trades when the Parabolic stop is rising, and Short trades when the Parabolic Stop is falling. After changing the Parabolic Stop properties, check the Use as Default check box so these parameters are used as the default settings.

Last modified 10/27/08 9:43 PM
|