Disclaimer: “Sequential™” is a registered trademark of Tom Demark. This post presents an independent, educational interpretation of the components of the Sequential™ pattern as described in Tom Demark’s book, The New Science of Technical Analysis. The analysis, opinions, and code examples provided herein are solely those of the author and are intended for informational and educational purposes only. This work is not affiliated with, endorsed by, or officially connected to Tom Demark or any related entities.
Sequential™ Pattern – Setup and Countdown
This pattern is fully described in Tom Demark’s book and consists of two distinct phases. For brevity’s sake, I will just discuss the buy setup. This indicator is designed to help determine when a trend is becoming or has become exhausted. Unlike a trend following indicator that helps you get in at the genesis of the trend, Sequential indicates when to take an opposing position after trend termination. This post doesn’t concern itself with the efficacy of Sequential, but with the process of programming such a difficult pattern and all the conditions that it involves. The indicator consists of two parts or phases. The Setup phase is stringent, requiring that the same price pattern occur for at least nine consecutive days (bars). In contrast, the Countdown phase is less strict; it mandates that a different price pattern occurs over a span of 13 days (or bars), although these occurrences do not need to be consecutive. Setup is complete when an “intersection” occurs, marking the point where prices start to brake or consolidate. Countdown, on the other hand, is finished when the 13th instance of the designated price pattern is observed. Because the pattern in the Countdown phase does not have to appear on consecutive bars, this phase can take many days to complete. During Countdown, three scenarios can occur that either restarts or recycles the process.
Setup – Sequence
close[0] > close[4]
followed by nine consecutive Close[0] < Close[4]
Intersection- Sequence
If nine bars fulfill the Setup then examine the following
Bar 8 High[1] > Lowest(Low[4],5)
Bar 9 High[0] > Lowest(Low[3],5)
Countdown – Sequence
13 days or bars fulfill Close[0] < Low[2] over any number of days
Sequential™ – Completion, Restart, Recycle
Completion – once Countdown reaches 13, the Sequential pattern is completed.
Restart – during countdown if a Close > Highest High during setup or a Sell Setup occurs – start either from scratch or start the Sell Countdown
Recycle – a new Buy Setup occurs, then start from the Countdown phase again.
Because we have to monitor a Sell Setup during the Countdown phase, we need to run two Finite State Machines concurrently. These two state machines will duel with each other. Both searching for their own solutions and knocking each other out during the process.
Finite State Machine Structure
Years ago, I embarked on building a theoretical compiler—a challenging project I nearly finished. The initial step was to create a parser that transforms high-level code into tokens according to the language’s grammar. In doing so, I learned about Finite State Machines (FSMs) as my program processed source code one character at a time and used FSM logic to build a token table.
Sample FSM to Find Pivot Highs and Pivot Lows
From this experience, I quickly discovered that even the most complex patterns can be detected using a Finite State Machine. Below is a graphical representation of a simple FSM that identifies the following pattern that can take up to 90 days (bars) to complete.
A high pivot with strength 2
Followed by a low pivot with strength 2
Followed by another high pivot with strength 2
In this example, a pivot is defined such that the central (or “pivot”) bar must have a higher high (for a high pivot) or a lower low (for a low pivot) than both the two bars preceding it and the two bars following it. Additionally, I also added the high pivot requires that the two prior bars exhibit ascending highs and that the two subsequent bars exhibit descending highs, while a low pivot follows the opposite pattern.
Finite State Machines (FSMs) consist of a limited number of states that describe the various conditions of a system:
Start State: The initial point where processing begins. Looking for the first Pivot High.
Intermediate States: The stages the FSM progresses through as it processes input. Looking for the first Pivot Low.
Terminal (or Accepting) States: The final state(s) indicating the system has completed its task. Locating the final Pivot High.
Transition logic (the “rules” for shifting between states) guides the FSM’s movement, and some FSMs include a timeout function that resets the machine if it stays in one state too long.
Transition from FSM State 0 to FSM State 1
Acting like Pac-Man, the FSM gobbles one bar at a time and looks for this pattern:
high[2] >high[1] – right side
high[1] >high[0] – right side
high[2] > high[3] – left side
high[3] > high[4] – left side
Transition from FSM State 1 to FSM State 2
Now we look for the specific low pivot pattern
low[2] <low[1] – right side
low[1] <low[0] – right side
low[2] < low[3] – left side
low[3] < low[4] – left side
Transition from FSM State 2 to Completion and then back to FSM State 0
The pattern is completed after the subsequent high pivot pattern is confirmed. Once completed the machine resets itself to FSM State 0.
high[2] >high[1] – right side
high[1] >high[0] – right side
high[2] > high[3] – left side
high[3] > high[4] – left side
FSM Clock Override
If the pattern is not recognized within 90 days or bars from the first pivot high, then the machine resets back to FSM State 0.
Pivot Point FSM Output
Simple FSM Output
Switch Case in EasyLanguage
When I started programming in Python, the Case statement was not included which shocked me. Since Python 3.10 it has been introduced. A Switch Case structure lets a program choose among several execution paths based on a variable’s value, using distinct cases instead of long if-else chains. This results in cleaner, more efficient, and more readable code. Take a look at the syntax of the Switch Case in EasyLanguage – remember much of the following code is dedicated to painting the bars.
Inputs: PivotStrength(3); // Strength parameter for pivot high detection
switch (FSMState) begin case 0: begin if h[2] > h[3] and h[3] > h[4] and h[2] > h[1] and h[1] > h then begin FSMState = 1; Print(d," First pivot high found: ",h[2]); barCount = 0; for j = 0 to 4 begin plotPB[j](h[j],l[j],"FSM PVT Patt.",yellow); end; end; end;
case 1: begin if l[2] < l[3] and l[3] < l[4] and l[2] < l[1] and l[1] < l then begin FSMState = 2; for j = 0 to 4 begin plotPB[j](h[j],l[j],"FSM PVT Patt.",red); end;
end; end;
case 2: begin if h[2] > h[3] and h[3] > h[4] and h[2] > h[1] and h[1] > h then begin FSMState = 0; for j = 0 to 4 begin plotPB[j](h[j],l[j],"FSM PVT Patt.",cyan); end; end; end;
end; // End case-switch
barCount = barCount + 1; if barCount = 90 then FSMState = 0;
Simple FSM to locate Pivot Point Pattern
The syntax is straightforward: the keyword switch is used, and the variable FSMState directs the flow through different case blocks. Initially, FSMState is set to 0, and a transition occurs only when the specified criteria are met. Once met, FSMState is updated to 1. EasyLanguage follows a non-fall-through paradigm—once a state transition occurs, no other case statements are evaluated during that iteration; the program simply reaches the end of the block and awaits the next cycle. By contrast, in some languages, when the state changes (for example, from 0 to 1), the corresponding case for state 1 may be evaluated immediately within the same cycle.
Is it as Complicated as it Looks?
Not at all. Look at the different case blocks and you will see a very similar structure. As stated earlier the code to paint the bars take up 12 lines of code. The timer is located at the bottom of the code – once barCount = 90, the FSM resets to 0.
Is Sequential ™ Easy to Program with a Finite State Machine?
I wouldn’t say easy, but I wouldn’t say hard either. With a little elbow grease and knowledge of how TradeStation works, and some EasyLanguage knowledge it is not difficult. If it were easy, you would see the code all over the place. I have previously programmed parts of it in my Easing into EasyLanguage books.
You might think you could have ChatGPT generate the code for you, and for laughs, I tried asking ChatGPT to program Sequential™ using FSM and Switch/Case in EasyLanguage. While the output provided a foundation, most of the syntax was off, and the patterns weren’t defined properly. Ultimately, I discovered that simplifying the design—by using separate FSMs for the buy side and the sell side—made the implementation more manageable. To simplify the process, I focused exclusively on the buy side at first. I figured that once I had programmed the complete pattern for the buy side, adapting it to the sell side would be as simple as reversing the logic—since the overall structure remains identical.
Using “Backward Scanning” for the Setup Phase.
Setup requires analyzing at least 10 consecutive bars. When you hear “consecutive,” think of looping through each bar in sequence. A stringent consecutive pattern is best uncovered by looping back through historical data. For example, you can loop through the bars to identify a sequence of nine consecutive bars where the close of the current bar is less than the low from four bars prior. However, immediately preceding those nine bars, you must verify that the prior bar’s close is greater than the close from four days earlier. This additional condition ensures the pattern begins under the correct circumstances.
Is there a Method to this Madness?
I’ve found that using methods in EasyLanguage is a real asset during development. Methods work like functions but are local to the module in which they’re defined, so all the code is right there for easy reference, debugging, and testing. I typically reserve methods for code segments that I’ll reuse multiple times, which helps keep my project organized and efficient as it grows. Here is the method that uses back scanning to uncover the Sequential Setup phase.
method bool seqBuySetup(int numConsDays) var: int result; begin
result = countif(c[0] < c[LookBack],suTarg); if result = numConsDays and c[suTarg]>c[suTarg+LookBack] then return(True) else return(False); end;
Notice the syntax of the method structure
You might not recognize all parts of this code at first glance. First, I’m using a method, and I must specify its return type as bool (Boolean) in the method header. This indicates that the method will return either True or False. I’m also passing an integer variable, numConsDays, into the method.
Inside, I use the countIf function to evaluate the relationship between close[0] and close[4]—with LookBack set to 4. Essentially, countIf counts how many times the condition close[0] < close[4] is met over a span of bars defined by suTarg (or SetUpTarg). If this count equals 9, I then compare close[9] with close[13]. If close[9] is greater, I determine that this portion of the Setup phase has been successfully completed.
Does close[0] mean today’s close or the close of what George has penned as the close of the Focus Bar.
close[0] – close of today – not really unless it is the last bar on the chart – we could call this the Focus Bar if not
close[1] – yesterday – 1 day back or 1 day prior to the focus bar
close[2] – 2 days prior
close[3] – 3 days prior
close[4] – 4 days prior
When you run a backtest in TradeStation, the engine iterates through every bar in your dataset—even though your chart window only shows a subset of those bars. To make this clear, I use the term Focus Bar for whichever bar is currently being processed as the system moves from left to right. Think of it like a big loop over all bars: when the loop index is 50, bar #50 is the Focus Bar and you reference its values with [0] (e.g., close[0]). When the loop advances to index 51, bar #51 becomes the Focus Bar—still accessed with [0]—and so on.
Here’s the key point: all price series—high, low, open, etc.—are zero‑indexed, so the Focus Bar is always referenced with index 0. That means the Focus Bar’s closing price is close[0], its high is high[0], and its low is low[0]. For instance, if the Focus Bar is dated January 3, 1999, and it completes the Setup phase, you’d paint it using high[0] and low[0]. Remember, close[0] only represents “today’s” close when you’re on the very last bar; otherwise, it simply refers to whatever bar is currently the Focus Bar during a historical back-test.
Take a look at the following method to see this in action.
method void paintBuySetup(int numPaintDays) var: int j; begin PlotPB[suTarg](High[suTarg],Low[suTarg],"DMSeq.",cyan,3); for j = 0 to numPaintDays-1 begin PlotPB[j](High[j],Low[j],"DMSeq.",yellow,3); end; end;
Looping from bar 0 to bar 8 or nine bars
Notice how I loop from 0 to numPaintBars-1 or 8 to paint the last nine bars in the sequence. If you want to paint bars in a back-scan make sure you use the same syntax I have used here. Use an offset for the PlotPB along with the same offset for each bar’s high and low in the loop.
PlotPB[j](High[j],Low[j],"DMSeq.",yellow,3); // j goes from 0 to 8
If I want to compare the 10th bar in my series, then I refer to it as close[9]. I compare the 10th bar with 13th bar (close[9 + 4]) to see if I have the genesis of the Setup phase. Bar number 0 is the first bar in the series going back in time (Focus Bar.) Could I offset everything by one bar to get rid of the 0 offset? Many people have a problem dealing with 0s so you could but if you want to turn this into a strategy and you want to execute on the next bar’s open, then you will need to stick with the 0. Let’s break each state down and you will see how I was able to program this monster.
FSM State 0 – Scanning for the first part of the Setup Phase
Case 0: // Find a long setup - retroactively if seqBuySetup(suTarg) then begin stateBuy = 1; SetupCountBuy = suTarg; SetUpHigh = highest(h,suTarg); if plotBuySetUp then paintBuySetUp(suTarg); end;
If the seqBuySetup method returns True, the FSM transitions to State 1 and SetupCount is set to 9. This triggers a look-back over the past nine bars to determine the highest high, which serves as a reset level in the Countdown phase if a close exceeds that value.
In the PaintBar routine, the user can choose to display the Sequential Buy Setup, the Sell Setup, or both. If the user opts to display the Buy Setup, the paintBuySetUp method is executed.
FSM State 1 – Looking for an Intersection
This state uses a hybrid approach to detect an intersection. Now that we’re in FSM State 1, we’re close to completing the first phase. We start by examining bars 8 and 9, which are the final two bars of the nine-bar setup from the latest data. First, we check if the high of bar 8 is greater than any of the low values in bars 5, 4, 3, 2, or 1—if it is, an intersection is found. If not, we compare the high of bar 9 with the low values in bars 6, 5, 4, 3, or 2. Should bar 9 also fail to meet the criteria, we then switch to forward scanning for any subsequent bar that fits the criteria. Note that the bars identified in the forward scan do not have to meet the same stringent conditions as the consecutive bars in the Setup phase. Eventually, a bar will meet the criteria, and we then can move to the Countdown phase also known as FSM State 2
Case 1: // Setup complete now look for intersection // may take a couple of days if SetupCountBuy = suTarg then begin //going back to get lowest lows of 5 bars //prior to bar 8 and bar 9 minLow1 = lowest(low[4],5); minLow2 = lowest(low[5],5); if (High[1] > minLow1 or High[2] > minLow2) then begin stateBuy = 2; CountdownCountBuy = 0; if close <= Low[2] then begin CountdownCountBuy = 1; if PlotBuySetup then PlotPB(High,Low, "DMSeq.",green); end; buyIntersectBarNum = barNumber; Value1 = MyColors("Orange"); Value2 = iff(High[1] < minLow1,2,1); if PlotBuySetup then PlotPB[value2](High[value2],Low[value2], "DMSeq.",value1); // paint intersection end; end;
Intersection
The Devil is in the Details
Counting bars is challenging. Because our FSM doesn’t fall through states after a transition, once the consecutive nine-bar sequence is complete, we’re already at the next bar—the tenth. To determine whether the high of the ninth bar exceeds the lows from earlier bars, I compare the high of bar 9 (denoted as high[1]) with the lowest low from three bars earlier (low[4]) across a range covering five bars. If necessary, I repeat a similar comparison, starting with the high of bar 8, using high[2] and the corresponding lows starting from low[5] over a five-bar range. There is a chance neither bar will fulfill the criteria. In this case we start forward scanning to see if high[1] fulfills the criteria. Could we check for high[0] if the bar 8 and bar 9 fail? You might be able to – it might be worth investigating. However, it will add more code. Given some time you’ll see that high[1] will form an intersection. For clarity, I introduced the term Focus Bar to refer to the bar at index [0] in the historical data. In this context, if high[1] represents the prior bar relative to the Focus Bar and meets the intersection criteria, we need to immediately assess the Focus Bar to determine if it signals the start of the Countdown phase. Why act now? Because, without fall-through in our FSM, once a state transition occurs, the Focus Bar, if examined in the next state, would be skipped—so it’s essential to evaluate the Focus Bar (today’s bar if last bar on chart) right away while we are in the current state. If close[0] < low[2], the bar is painted with the Countdown theme color and this phase begins and the state machine transitions
FSM State 2 – Looking for a completion of Countdown
We are almost there. All we need are 13 bars that fulfill this criteria, close[0] < low[2]. From this point on we will be forward scanning and counting bars that fit the previously mentioned criteria. Once we reach 13, we are done. Finally, our journey to program the Sequential has come to an end. Or has it? So far, the description of the pattern has been straightforward, and we are in the home stretch? The completion of 13 bars who’s close[0] < low[2] can take many days to complete and many things can happen during this time. In his book, Tom Demark mentions three things that can derail the completion of the Countdown phase. This is where the fun really begins.
Case 2: // Sell Countdown Phase if close <= Low[2] then begin CountdownCountBuy = CountdownCountBuy + 1; if PlotBuySetup then PlotPB(High,Low, "DMSeq.",green); // Generate a buy signal end; if CountdownCountBuy = ctTarg then begin if PlotBuySetup then begin value99 = Text_new(d,t,low - range*0.2,"B"); PlotPB(High,Low, "DMSeq.",red); // Generate a buy signal end; resetBuyFSM(); end;
Portion of FSM State 2 that looks for and paints Countdown bars
This code is very simple – paint the bar if close[0] < low[2] and then count the bar. Once the number of bars = ctTarg (CountDown Target). then place the letter “B” above the high and paint the bar a different color. Sequential is now complete and so the Buy Finite State Machine needs to be reset. Bar are we really done?
Countdown derailment
If a close exceeds the highest high during Setup – restart the process from scratch – reset the FSM
If a Sell Setup completes while waiting for the 13 bars – cancel the Buy Countdown and start the Sell Countdown
If a fresh Buy Setup reveals itself, recycle and restart the Countdown process.
// Invalidate buy countdown if // 1.) a close > high during setup // 2.) a sell setup occurs // 3.) recycling occurs - new buy setup if c > SetupHigh then resetBuyFSM(); if stateSell = 2 then resetBuyFSM(); if (seqBuySetup(suTarg) and barNumber - buyIntersectBarNum > suTarg) then begin stateBuy = 1; SetupCountBuy = suTarg; CountdownCountBuy = 0; if plotBuySetUp then paintBuySetup(suTarg); SetUpHigh = highest(h,suTarg); end;
2ND half of FSM State 2
The Dueling Nature of this Pattern Recognition Tool often prevents Sequential from reaching Completion – maybe a good thing.
Well, that is part of the reason. The recycle of the Setup is also a culprit. Because the pattern for the Buy and Sell requires the consumption of so many bars, the two FSM must run independent of each other and at times contradict each other. Here is as good example of the FSMs taking action in the recent (April 2025) GOLD market. Click on images to expand.
Wow! What a great buy!It started out really great, but like any Trend Following approach…Months to Complete
Sequential™ Examples
Shampoo, Rinse, Repeat. Bingo!
We had 4 complete buy Setups with interrupted Countdowns
We had 4 complete buy Setups with interrupted Countdowns before it finally stuck!
Count-Downus Interruptus
Blow off top with Buy Setup completion interrupts the short Countdown.
Sell Countdown interrupted by Buy Setup
Market congestion, just like smoking, stunts growth of patterns.
Congestion Phase validated by incomplete Sequential Setups and Countdowns
Many Complex Patterns can be Programmed by using Multiple FSMs
Almost anything can be programmed with EasyLanguage and the concept of a Finite State Machine and the Switch-Case structure. If you don’t know where to start, ask ChatGPT with the best and most descriptive prompt you can come up with. Then start small and build up – always check your progress before moving on to the next phase. Email me with any questions and if you like this type of content check out my books at Amazon.
Last Trade Was a Loser Filter – To Use or Not To Use
Premise
A major component of the Turtle algorithm was to skip the subsequent 20-day break out if the prior was a winner. I guess Dennis believed the success/failure of a trade had an impact on the outcome of the subsequent trade. I have written on how you can implement this in EasyLanguage in prior posts, but I have been getting some questions on implementing FSM in trading and thought this post could kill two birds with one stone: 1) provide a template that can be adapted to any LTL mechanism and 2) provide the code/structure of setting up a FSM using EasyLanguage’s Switch/Case structure.
Turtle Specific LTL Logic
The Turtle LTL logic states that a trade is a loser if a 2N loss occurs after entry. N is basically an exponential-like moving average of TrueRange. So if the market moves 2N against a long or short position and stops you out, you have a losing trade. What makes the Turtle algorithm a little more difficult is that you can also exit on a new 10-day low/high depending on your position. The 10-day trailing exit does not signify a loss. Well at least in this post it doesn’t. I have code that says any loss is a loss, but for this explanation let’s just stick to a 2N loss to determine a trade’s failure.
How To Monitor Trades When Skipping Some Of Them
This is another added layer of complexity. You have to do your own trade accounting behind the scenes to determine if a losing trade occurs. Because if you have a winning trade you skip the next trade and if you skip it how do you know if it would have been a winner or a loser. You have to run a theoretical system in parallel with the actual system code.
Okay let’s start out assuming the last trade was a winner. So we turn real trading off. As the bars go by we look for a 20-Day high or low penetration. Assume a new 20-Day high is put in and a long position is established at the prior 20-Day high. At this point you calculate a 2N amount and subtract if from the theoretical entry price to obtain the theoretical exit price. So you have a theoMP (marketPosition) and a theoEX (exit price.) This task seems pretty simple, so you mov on and start looking for a day that either puts in a new 10-Day low or crosses below your theoEX price. If a new 10-Day low is put in then you continue on looking for a new entry and a subsequent 2N loss. If a 2N loss occurs, then you turn trading back on and continue monitoring the trades – turning trading off and then back on when necessary. In the following code I use these variables:
state – 0: looking for an entry or 1: looking for an exit
lep – long entry price
sep– short entry price
seekLong – I am seeking a long position
seekShort – I am seeking a short position
theoMP – theoretical market position
theoEX – theoretical exit price
lxp – long exit price
sxp – short exit price
Let’s jump into the Switch/Case structure when state = 0:
Switch(state) Begin Case 0: lep = highest(h[1],20) + minMove/priceScale; sep = lowest(l[1],20) - minMove/priceScale; If seekLong and h >= lep then begin theoMP = 1; theoEX = maxList(lep,o) - 2 * atr; // print(d," entered long >> exit at ",theoEX," ",atr); end; If seekShort and l <= sep then begin theoMP = -1; theoEX = minList(sep,o) + 2 * atr; end; If theoMP <> 0 then begin state = 1; cantExitToday = True; end;
State 0 (Finite State Set Up)
The Switch/Case is a must have structure in any programming language. What really blows my mind is that Python doesn’t have it. They claim its redundant to an if-then structure and it is but its so much easier to read and implement. Basically you use the Switch statement and a variable name and based on the value of the variable it will flow to whatever case the variable equates to. Here we are looking at state 0. In the CASE: 0 structure the computer calculates the lep and sep values – long and short entry levels. If you are flat then you are seeking a long or a short position. If the high or low of the bar penetrates it respective trigger levels then theoMP is set to 1 for long or -1 for short. TheoEX is then calculated based on the atr value on the day of entry. If theoMP is set to either a 1 or -1, then we know a trade has just been triggered. The Finite State Machine then switches gears to State 1. Since State = 1 the next Case statement is immediately evaluated. I don’t want to exit on the same bar as I entered (wide bars can enter and exit during volatile times) I use a variable cantExitToday. This variable delays the Case 1: evaluation by one bar.
State = 1 code:
Case 1: If not(cantExitToday) then begin lxp = maxList(theoEX,lowest(l[1],10)-minMove/priceScale); sxp = minList(theoEX,highest(h[1],10)+minMove/priceScale); If theoMP = 1 and l <= lxp then begin theoMP = 0; seekLong = False; if lxp <= theoEX then ltl = True Else ltl = False; end; If theoMP =-1 and h >= sxp then begin theoMP = 0; seekShort = False; if sxp >= theoEX then ltl = True else ltl = False; end; If theoMP = 0 then state = 0; end; cantExitToday = False; end;
State = 1 (Switching Gears)
Once we have a theoretical position, then we only examine the code in the Case 1: module. On the subsequent bar after entry, the lxp and sxp (long exit and short exit prices) are calculated. Notice these values use maxList or minList to determine whichever is closer to the current market action – the 2N stop or the lowest/highest low/high for the past 10-days. Lxp and sxp are assigned whichever is closer. Each bar’s high or low is compared to these values. If theoMP = 1 then the low is compared to lxp. If the low crosses below lxp, then things are set into motion. The theoMP is immediately set to 0 and seekLong is turned to False. If lxp <= a 2N loss then ltl (last trade loser) is set to true. If not, then ltl is set to False. If theoMP = 0 then we assume a flat position and switch the FSM back to State 0 and start looking for a new trade. The ltl variable is then used in the code to allow a real trade to occur.
Strategy Incorporates Our FSM Output
vars:N(0),mp(0),NLossAmt(0); If barNumber = 1 then n = avgTrueRange(20); if barNumber > 1 then n = (n*19 + trueRange)/20;
If useLTLFilter then Begin if ltl then buy next bar at highest(h,20) + minMove/priceScale stop; if ltl then sellShort next bar at lowest(l,20) -minMove/priceScale stop; end Else Begin buy next bar at highest(h,20) + minMove/priceScale stop; sellShort next bar at lowest(l,20) -minMove/priceScale stop; end;
mp = marketPosition;
If mp <> 0 and mp[1] <> mp then NLossAmt = 2 * n;
If mp = 1 then Begin Sell("LL10-LX") next bar at lowest(l,10) - minMove/priceScale stop; Sell("2NLS-LX") next bar at entryPrice - NLossAmt stop; end; If mp =-1 then Begin buyToCover("HH10-SX") next bar at highest(h,10) + minMove/priceScale stop; buyToCover("2NLS-SX") next bar at entryPrice + NLossAmt stop; end;
Strategy Code Using ltl filter
This code basically replicates what we did in the FSM, but places real orders based on the fact that the Last Trade Was A Loser (ltl.)
Does It Work – Only Trade After a 2N-Loss
Last Trade Loser In Action
Without Filter on the last 10-years in Crude Oil
With Filter on the last 10-years in Crude Oil
I have programmed this into my TradingSimula-18 software and will show a portfolio performance with this filter a little later at www.trendfollowingsystems.com.
I had to do some fancy footwork with some of the code due to the fact you can exit and then re-enter on the same bar. In the next post on this blog I will so you those machinations . With this template you should be able to recreate any last trade was a loser mechanism and see if it can help out with your own trading algorithms. Shoot me an email with any questions.
Backtesting with [Trade Station,Python,AmiBroker, Excel]. Intended for informational and educational purposes only!
Get All Five Books in the Easing Into EasyLanguage Series - The Trend Following Edition is now Available!
Announcement – A Trend Following edition has been added to my Easing into EasyLanguage Series! This edition will be the fifth and final installment and will utilize concepts discussed in the Foundation editions. I will pay respect to the legends of Trend Following by replicating the essence of their algorithms. Learn about the most prominent form of algorithmic trading. But get geared up for it by reading the first four editions in the series now. Get your favorite QUANT the books they need!
The Foundation Edition. The first in the series.
This series includes five editions that covers the full spectrum of the EasyLanguage programming language. Fully compliant with TradeStation and mostly compliant with MultiCharts. Start out with the Foundation Edition. It is designed for the new user of EasyLanguage or for those you would like to have a refresher course. There are 13 tutorials ranging from creating Strategies to PaintBars. Learn how to create your own functions or apply stops and profit objectives. Ever wanted to know how to find an inside day that is also a Narrow Range 7 (NR7?) Now you can, and the best part is you get over 4 HOURS OF VIDEO INSTRUCTION – one for each tutorial.
Hi-Res Edition Cover
This book is ideal for those who have completed the Foundation Edition or have some experience with EasyLanguage, especially if you’re ready to take your programming skills to the next level. The Hi-Res Edition is designed for programmers who want to build intraday trading systems, incorporating trade management techniques like profit targets and stop losses. This edition bridges the gap between daily and intraday bar programming, making it easier to handle challenges like tracking the sequence of high and low prices within the trading day. Plus, enjoy 5 hours of video instruction to guide you through each tutorial.
Advanced Topics Cover
The Advanced Topics Edition delves into essential programming concepts within EasyLanguage, offering a focused approach to complex topics. This book covers arrays and fixed-length buffers, including methods for element management, extraction, and sorting. Explore finite state machines using the switch-case construct, text graphic manipulation to retrieve precise X and Y coordinates, and gain insights into seasonality with the Ruggiero/Barna Universal Seasonal and Sheldon Knight Seasonal methods. Additionally, learn to build EasyLanguage projects, integrate fundamental data like Commitment of Traders, and create multi-timeframe indicators for comprehensive analysis.
Get Day Trading Edition Today!
The Day Trading Edition complements the other books in the series, diving into the popular approach of day trading, where overnight risk is avoided (though daytime risk still applies!). Programming on high-resolution data, such as five- or one-minute bars, can be challenging, and this book provides guidance without claiming to be a “Holy Grail.” It’s not for ultra-high-frequency trading but rather for those interested in techniques like volatility-based breakouts, pyramiding, scaling out, and zone-based trading. Ideal for readers of the Foundation and Hi-Res editions or those with EasyLanguage experience, this book offers insights into algorithms that shaped the day trading industry.
Trend Following Cover.
For thirty-one years as the Director of Research at Futures Truth Magazine, I had the privilege of collaborating with renowned experts in technical analysis, including Fitschen, Stuckey, Ruggiero, Fox, and Waite. I gained invaluable insights as I watched their trend-following methods reach impressive peaks, face sharp declines, and ultimately rebound. From late 2014 to early 2020, I witnessed a dramatic downturn across the trend-following industry. Iconic systems like Aberration, CatScan, Andromeda, and Super Turtle—once thriving on robust trends of the 1990s through early 2010s—began to falter long before the pandemic. Since 2020 we have seen the familiar trends return. Get six hours of video instruction with this edition.
Pick up your copies today – e-Book or paperback format – at Amazon.com