In Search of the Holy Grail
by Howard Arrington

In literature, the 'Holy Grail' is generally considered to be the cup from which Christ drank at the Last Supper and the one used by Joseph of Arimathea to catch his blood as he hung on the cross.  The term 'holy grail' has been used among traders to represent the ultimate mechanical trading system that would return unlimited wealth.  Though many seasoned traders say the Holy Grail does not exist, it is a never ending pursuit of many traders to find a Holy Grail.  Armed with a computer as a research tool, thousands of traders have tested their ideas against historical data sets in search of the ultimate trading system.  Many ideas are marketed, surrounded by claims of phenomenal success with graphs showing the hypothetical accumulation of wealth if the system had been used to trade financial markets over the past few years.  Many of these mechanical systems are promoted with 'rags-to-riches' testimonials in the advertising literature which arrives unsolicited in my mail box each week.

Perhaps it has been my luck to just be unlucky.  The $3000 systems I am familiar with have ended up being more phony than legitimate.  Thus,  my bias is more likely to embrace the philosophy that the Holy Grail does not exist.  I consider the following are very valid questions to ask about any system being offered.  

  • Why does an author bother to sell a trading system if it does all that the author claims?
  • Why doesn't the author acquire unlimited wealth by using his Holy Grail, instead of being bothered with advertising, marketing, trade shows, customer support, and criticism?
  • Has the system withstood the test of time?   If it was 'holy' a decade ago, shouldn't it still be highly sought after now?
  • What happened to the 'rags-to-riches' folks who had their testimonials published a year ago?

Sorry I do not have the answers to these questions.  However, the real purpose of this article is to discuss the challenges of designing mechanical trading systems.  Consideration of these principles in one's design should be helpful to those who engage in a search for the Holy Grail.

1) Type of Market

We all realize that there are different types of markets, namely:  trending, swing, and choppy.  Different systems try to take advantage of a particular type of market, and their results look great when applied to the type of market they were designed for.  These systems have poor results in the wrong type of market.   System designers feel they have a great system if they can put money in the bank when the market is the right type, and break even when the market is the wrong type.

Studies serve as a basis for the design of many trading system, or are used as either a filter or a signal in the system design.   The following common studies have been categorized by the type of market they work best with.

  • Trending - Moving Averages, Parabolic Stop, Volatility Stop, Trailing Stop, Directional Movement Index, Channels
  • Swing - Stochastics, Relative Strength Index, MACD, Commodity Channel Index, Pesavento Patterns, Fibonacci, Divergence
  • Choppy - can't think of anything that works well with choppy.  Most traders prefer to stand aside in choppy markets.

Traders often try to label the Elliot wave counts so they can anticipate the type of market unfolding, whether the market is in a consolidating wave 4 triangle, or whether a wave 3 breakout thrust is underway.   They can then adjust their trading strategy for the type of market.

2) Slippage

Some systems suffer from trading too frequently.   Commissions and slippage costs become a high percentage of the expected gain.  For example, if two systems both generate a profit of $4000, would you prefer system A that did so with 10 trades or system B that did so with 100 trades?   The average trade in system A is $400 while the average trade in system B is $40.  For example, if the fills in real life are one tick worse in the E-mini markets, $25 has evaporated from the average trade results, and the penalty on 100 trades is more severe than on 10 trades.   Thus, a big factor to consider in evaluating a system's success record is the number of trades.   Too few trades may not be statistically sound, and too many trades may suffer from commissions and slippage losses, not to mention the constant wear it is on one's emotions.

3) Emotion

Emotion is one of the hardest areas to design for.   The whole reason traders seek a Holy Grail is because they have had a few bad experiences in the markets, and no longer trust themselves to trade well..  They assume that the computer can analyze the facts more logically and pull the trigger more mechanically, which are areas they feel they need help with.  The results look good on paper, up $60,000 for the year with the system, and the maximum draw down looks tolerable compared to the benefit.  So, courage is mustered and commitment to faithfully follow the system's signals is expressed to one's friends.  

But what happens over the next couple weeks.   Our emotions want instant success.  We are unwilling to tolerate a series of losing trades.   All systems eventually have a string of losing trades and a draw down in equity.  Such is part of the statistical results buried somewhere in those beautiful graphs of wealth accumulation.  However, a graph of past performance is emotionless.  The real thing, with my money on the line, is 100% emotion.  When I am ahead I am elated at how easy it is.  When I am behind, I start to second guess every signal and think I am smarter than the system, and I can improve on the trading system by applying my experience.  Surely I am aware of intangibles the system failed to consider.  For example, does the trading system know what is the correct thing to do when the news is showing horrifying pictures of planes flying into tall buildings, or war has broken out in the Middle East, or the dock workers have decided to go on strike, or Greenspan is speaking before Congress?  Suddenly we convince ourselves we know more than the Holy Grail system, and we abandon it as we seek a place of greater personal comfort.

It is easier to design a mechanical system than it is to actually trade it!   I know... I have been there and done that.

4) Now you see it, now you don't

One problem when doing analysis on a daily data set is the urge to jump the gun and execute a new signal during the day.  For example, you may see study lines cross during the day, which would constitute a signal, and you want to execute the trade now before the market runs away from you.  However, signals based on a daily data set only know the four prices of Open, High, Low and Close.   During the day the Open is known.  However, the High and Low are moving targets.  And the Close in not known until the market closes.  To execute any trade based on a signal during the day is to jump the gun.

Though you see the signal intra-day, the signal conditions will often undo themselves.  For example, a simple signal might be when the Close is above the Open.   When the market is putting in new highs, the signal condition is True.  However, the market can turn around and put in new lows wherein the signal condition has reversed to being False.   Signals which incorporate the Close price either directly or indirectly through studies should analyze through the last completed bar on the chart, and avoid giving a signal during the time period the current bar is under construction.  Otherwise they will suffer from the "'now you see it, now you don't" challenge.

5) Moving target

One of the unique studies in Ensign Windows is the Pesavento Patterns tool.  The program uses its set of proprietary rules to identify swings and label them with their percentage of retracement when compared to other swing.  The problem with using a study like this for a signal is that the target can move, as illustrated by this sequence of 3 charts.

Here the price has dipped to a swing low of 992.50, and the swing ratios are favored 1.128 and .841.  One might think there is a Buy signal in effect because of the ratios and the pattern.   If the markets were to rally, buying the apparent signal would look like a stroke of genius.  Now consider what happened.

The market dribbled higher in sideways chop between 12:30 and 14:00, then fell to a new low at 991.50.  The Pesavento Pattern tool adjusted to used the new swing low.  At 991.50 we have another favored ratio of 1.0 for a double bottom.  Do we have a buy signal at this double bottom?  Well consider what happened next.

The market traded lower into the close and the Pesavento Patterns tool adjusted again to this new swing low.  None of the bounces off of the prior swing low points were of sufficient amplitude to qualify as a new up trend because our minimum swing size parameter was set for 5 points.  Fluctuations under 5 points in size are being ignored by the Pesavento Patterns tool.

The tool illustrates a general problem where it is easier to see things with the benefit hindsight.   This can be said about most divergence patterns.  It is easy to see the last divergence where the market finally turned.  It is easy to overlook other divergence patterns that existed at the time, but were not the ones to be traded once additional bars were added to the chart and they became obscured by a subsequent pattern.  Often the patterns we seek to identify, the divergences, the study lines crossing, are a moving target.  In hindsight it is easy to say, "Of course, there it is, I see it"  yet in real-time we are frustrated by seeing similar patterns and signals prematurely in the moving target.  If we wait for the signal to be confirmed we are often late in our execution.  For example, it will be 5 points after the fact before we know for sure the current Pesavento Pattern is not going to adjust again to a new lower low.

6) Interior sequence

Another challenge in back testing a signal idea is the loss of detail in looking at historical bars versus knowing a real time tick sequence.  Consider a signal where we want to buy when the market rises 1 full point.  In this bar example we do not know whether the High was put in before or after the Low.

So in back testing, is the buy signal at 994.50, which would be the case if the market opened, and then went to the low of 993.50 and then rallied back to 994.50?  Or is the signal at the high of 995.50, which would be the case if it rallied from the 994.50 open to put in the high first?   We cannot tell.  We simply lack the detail of knowing the interior sequence of how the bar came to be.  The only thing known about the bar are the four fixed prices of its Open, High, Low and Close.

Another illustration of the interior sequence challenge is this.  Let's assume the Buy signal was one tick higher than the high of the bar on the left.  The buy trigger would be a known price of 995.50, and since the bar traded at that price, we can assume the position was filled.  Now suppose our protective stop is an automatic 2 points below our fill price.   Are we in or out of this trade on this bar?   The answer all depends on the sequence.  If the Low was put in prior to the High, then we have not been stopped out.  If the Low was put in after the order was executed, then the position is stopped out for a loss.  What happened is uncertain because the detail of how the bar was constructed is unknown in the historical data set. 

7) Execution price

I often find fault with the price chosen for execution.   A trading system I recently looked at used for its Sell price the High of the bar following the signal.  What a phony deal!  Using the High of any bar is biasing the sell statistics to be executed as a most favorable and unlikely price.  Likewise, using the Low of any bar as the execution price is biasing the buy statistics with a favorable and unlikely price.

My opinion is that the execution price should be the Open of the bar following the signal.  A second choice could be the Close of the bar that generated the signal.  While this is a fixed price in your historical data set, it is a moving target in real-time and leads you to anticipate the price or the signal just prior to the close of the bar.  We have already talked about this challenge in our "Now you see it, now you don't" discussion.

Another consideration is whether the execution price is a study value, such as a Parabolic Stop value, or a bar price such as its Close.  When a bar touches the Parabolic Stop, did you have a buy or sell stop in place to execute your trade?   That is fine if your system was designed for the trigger to be the Low or High of the bar touching the stop, as opposed to the bar closing across the stop.  If your signal is based on where the bar closes, then the execution price should be the bar's Close price and not the study value.  Also, the study value might be unrealistic if the bar gapped across the line, in which case the Open price of the gap bar should be used as the execution price. 

8) Time of day

Many day traders want a system that incorporates the time of day in its consideration.   Some systems are designed to avoid the choppiness of the market open.  Others may want to consider avoiding new trades near the close of the day.  Some systems will want to exit all positions ahead of the market close.

I find fault with scalping systems that establish trades just prior to market close, are blind to all Globex activity, and then exit at an excessive profit objective at the following day's favorable gap open.   My opinion is that scalping systems are day trading systems and their statistical results should not include holding positions overnight, nor be blind to the Globex trading if a position is held past the day session close.

9) Optimization

The computer lends itself to endless number crunching.  System designers adjust parameters endlessly in an effort to tweak more performance out of their idea.   They will adjust study parameters such as the number of bars in a moving average, adjust trigger thresholds such as CCI crossing 100, adjust entry and exit rules, and adjust slack parameters such as a stop offset from a bar high or low.  The number of possibilities is mind boggling.  The billions of calculations, permutations and combinations are unfathomable.   

When it is all said and done, the author announces the greatness of his work, expounds on the difficulty of the project and the cleverness of his creativity.  A price tag is picked, advertising hype assembled, and marketing efforts directed at would be buyers.

The problem is that the system performance is often over optimized in an effort to tweak great performance out of the historical data set used to design the system.  When I started Ensign Software 22 years ago, one of my first products was the CAT program (Computer Analyzed Trading).  It basically was a High/Low stop concept with an optimized slack value for each futures symbol.   CAT had an optimized slack value for Japanese Yen, a different slack value for Gold, and a different slack value for Live Cattle.  The idea was to put the good trends in the bank, and hold its own in choppy markets.  A really good trend came along in each market a couple times each year, and the impressive wealth accumulation was to catch those trends and put them in the bank.  The other 9 or 10 months of the year, the small winners would balance out the small losers.

The downfall of the system was over optimization.  Trading the program signals in real-time did not amass the same results as the back tested results.  Why?   It took a long time for me to admit to what the problem was because of my ego.  The system was being optimized to find a slack value for each market such that the stops would be far enough away to optimally avoid whip lash.   This meant we back tested tighter stops (enter and exit the trade sooner for more profit per trade) and wider stops (try to avoid whip-lash).   Somewhere between these conflicting objectives would be some slack values that would show positive returns in the back testing results.  The finely tuned slack values that generated 80+% winning trades, were valid for the historical data set the analysis was done on, but were not necessarily the best values to use for the immediate future.  The hope was, and it was definitely just a hope, that the past would repeat itself in the future and so the optimized parameters should continue to work.  Sometimes they did, often they did not.

When you see advertisements showing stellar results, please realize that the graphs and reports show Optimized settings, optimized for the past.  And wisely the small print says, "Past performance is no guarantee of future performance."   Trust me... future performance will be worse than the past performance because the past was optimized.

10) Just one more rule

The dilemma with every system designer is that their work is never done.   They are plagued with the perpetual need to add just one more rule to handle just one more situation that just came up in today's market that was not handled as profitably as it should.   If only we had one more rule too keep us out of that losing trade today, then the system would be perfect.  So one more rule, one more exception is incorporated into the system.  But the process is repeated over and over again as the original pure idea evolves into a different beast.

One more rule is just another form of on-going optimization.  Often this type of optimization is based on what happened today, and not on thorough back testing.  I have seen systems that worked in general and were statistically proven through back testing, become specialized and cease to work at all because of the addition of rules to handle special situations.  Rules get added to avoid opening gaps that exceed a certain threshold, or to avoid trading during certain windows of time during the day, or to increase the trade size if a particular formation is seen, etc.  Too often the rules use specific hard coded values instead of being generalized so they auto adapt to different instruments or auto adapt to calmer or more volatile markets.

I guess the lure to harvest more money from the field of opportunity will keep the Holy Grail seekers forever employed.  Not all will agree on the ideas on which different mechanical system are founded.   One trader shooting for the moon might be confident even when a big position is against him 20 thousand dollars, while other traders would be financially and emotionally wiped out.  We each have a different 'risk avoidance' threshold and comfort zone.  May each of you find a methodology that fits your personality and pocket book, and helps you be successful in your trading.


Research:
Back Testing
by Howard Arrington

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, http://www.ensignsoftware.com/espl/espl.htm

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.

  1. It must trade in the direction of the trend.   Trade 'short' in a downtrend and 'long' in an uptrend.
  2. It must have specific, mathematical rules that define the 'signals' for buying, selling, and exiting a position.
  3. Parameters should be flexible so that different settings can be tried and tested.
  4. 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.

 

{define global variables}
var
  Position: integer;
  EntryPrice: real;
  ExitPrice: real;
  ExitStop: real;
  ScalpSize: real;
  StopSize: real;
  HH: real;
  LL: real;

  BuySignal: boolean;
  SellSignal: boolean;
  TrendUp: boolean;
  TrendDn: boolean;

{define procedures and functions}
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;

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;

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;

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;

procedure Report;
begin
  Trade(eOut); {close-out the last open trade}
  TradeReport(True); {print the results in the output window}
end;

{main program}
begin
  Initialize;
  Calculate;
  Report;
end;

Back Test Results

For all tests, a $10 round trip commission will be used.  The chart being tested is the 3 minute ES #F.  The data set has been limited to Day Session Only data for the three dates of June 20th, 23rd, and 24th.

For the first test, let's try a small scalp objective of one full point, and a generous stop size of 2.50 points.   The following are the back test results, and the chart shows some of the trades.

ES #F   Profit  Trades  Average  Ratio
Wins   1435.00      34    42.21  79.07
Loss   1215.00       9   135.00  20.93
Total   220.00      43     5.12   1.18

79% of the trades were profitable scalps, but the Net Profit is only $220 after paying commissions on 43 trades.  Let's try a bigger scalp objective, knowing in advance a lower percentage of winning trades will be achieved.  The following results are for a scale objective of 2.50 points.

ES #F   Profit  Trades  Average  Ratio
 Wins   1675.00      15   111.67  62.50 
 Loss   1215.00       9   135.00  37.50 
 Total   460.00      24    19.17   1.38 

The larger scalp objective generates more profit, on fewer trades, which is good on both points.   

Further testing could be done with this trade system to determine whether one should use a tight or a generous stop, and whether the scalp objective should be large or small.  The parameters for the Parabolic stop should also be adjusted to see the impact it has on the trade system.  Finally, the system should be tested using more data to simulate a wider variety of market conditions.   Some may wish to modify the logic for the Buy and Sell signals to test other ideas.  The tools are available in Ensign Windows for designing trade systems and the effort can be both rewarding and fun