< All Topics

MultiWalk, EasyLanguage and Strategy Good Coding Practices

Over the years there are some good practices that I have adopted that help avoid some of the pitfalls, bugs or logic issues when writing strategies in TradeStation or running lengthy MultiWalk projects. I detail several below.

MultiWalk Projects

MultiWalk projects can be take a long time to run, but there are some things you can do to help minimize run times and maximize results.

Don’t use LIBB on initial, large runs

TradeStation’s Look-Inside-Bar Backtesting option adds a critical component to the backtest simulation. It gives a better estimate of a trade’s fill price that cannot always be derived from the strategy’s open/high/low/close bar values. However, this comes as a huge performance cost, both in terms of memory consumption and computational time. It can double to triple the amount of time it takes a project to optimize. For this reason I do NOT use LIBB for large, initial MultiWalk projects. But once I identify a smaller set of results that I want to analyze, I will create a new project with just those symbols and bar intervals and then use LIBB to further refine the results.

Computer Power

MultiWalk is “resource heavy” and requires a certain amount of computer power. See this article for minimum recommended hardware configurations. But don’t think

Use Limited Feasibility Testing as an optimization pre-filter

MultiWalk implements Kevin Davey’s limited feasibility testing methodoloty as a pre-filter to skip worthless symbols/bar interval results.  Do not disable this option unless you have good reason:

The optimization phase takes the most time in a MultiWalk project, so anything we can do to limit the amount of time spent optimizing is worthwhile. It means better and faster results rather than wasting time on symbol and bar combinations that would probably not be profitable. This is a critical time-saver in MultiWalk.

Run Multiple MultiWalk Instances

If you have multiple projects, or can divide your project up into two or three MultiWalk projects (such as giving each a set of different symbols), then you can maximize the run time by running multiple MultiWalk projects simultaneously.  As a rule-of-thumb, divide the number of threads of your CPU by the number of projects you want to run simultaneously as set it for each project:

Due to limitations within TradeStation’s design, there are no speed gains setting this value greater than 10.  See this article for more information.

Running multiple projects will compound the amount of memory (RAM) used, so care must be taken not to exceed TradeStation’s 32-bit memory limit.  If this occurs, you will receive a warning from MultiWalk.  Simply decrease the number of threads and resume your project(s).

Do NOT use cloud based storage drives for TradeStation OR MultiWalk

Quite a while ago I had the great idea to put my TradeStation work folders into Sync, my cloud-based drive service, so that I could easily go back and forth between my desktop and laptop when working on strategies or MultiWalk.  I found out the hard way that this is a bad idea.  I quickly corrupted the entire TS EasyLanguage database when I tried to mirror my TradeStation user documents folder using my sync.com account.  I had to perform a complete restore from a recent backup.  The same thing happened with DropBox, OneDrive or any other cloud sharing service.

This is also true when running MultiWalk projects.  Using a drive or folder that is being monitored by a cloud-based file sharing service will quickly corrupt the MultiWalk project.

Backup your files!

Enable TradeStation’s backup feature.  You never know when you might have to restore your work!

TradeStation and Trade Orders

The rule-of-thumb I apply to all buy/sell/sellshort stop and/or limit orders is to never assume that the orders are going to execute the way that you think they will and never assume that TradeStation will somehow compensate for unclear trade orders in your strategy.

Entry Orders

Assuming that we are following the Strategy Factory Club protocol and only trading N contracts at a time, then we could simply write the following code for long or short market entries as:

if ( RSI(Close,2) < 20 ) then buy next bar at market;
if ( RSI(Close,2) > 80 ) then sellshort next bar at market;

However, there are conflicting results when using LIBB (Look-inside-bar backtesting) or not. Using LIBB, TradeStation’s backtest engine will exit a stop and then immediately enter the trade again in the same direction. In a sense it is like not having a stop at all. If you do not use LIBB, then the trade is stopped out as expected and the position is not re-entered. Kevin reported this bug to TS in this post and Elihay, A TS forum member and Strategy Factory member, found a solution by qualifying the entry like this:

if ( RSI(Close,2) < 20 and MarketPosition <> 1  ) then buy next bar at market;
if ( RSI(Close,2) > 80 and MarketPosition <> -1 ) then sellshort next bar at market;

Now the trade results are the same whether using LIBB or not.

Exit Market Orders

In a related subject for exits, we could simply write the following code to exit any short or long positions:

if ( some_exit_criteria ) then
begin
   sell next bar at market;
   buytocover next bar at market;
end;

However, I have found that, for exiting positions, that the above code will sometimes cause unexpected interactions with other orders and cause a “hiccup” in the order flow by placing an additional order that results in an immediate entry and exit. While this will cause an extra commission/slippage cost (granted a minimal concern in the scheme of things), my primary concern is possible order confusion, either from the backtest engine or at the order desk.  I call this the “same entry/exit” (TradeSameEntryExit)  issue and write in more detail about it in this article.

This order situation can be avoided by adding this simple qualification:

if ( some_exit_criteria ) then
begin
   if ( MarketPosition = 1  ) then sell next bar at market;
   if ( MarketPosition = -1 ) then buytocover next bar at market;
end;

Entry or Exit Stop Orders

Stop orders are a bit of a different situation.

Instead of this:

sell ("MW StopLoss-L") next bar at longprice stop; 
buytocover ("MW StopLoss-S") next bar at shortprice stop; 

You could do this:

if ( MarketPosition = 0 or MarketPosition = 1 ) then
    sell ("MW StopLoss-L") next bar at longprice stop; 

if ( MarketPosition = 0 or MarketPosition = -1 ) then
    buytocover ("MW StopLoss-S") next bar at shortprice stop; 

Some strategies, such as breakout strategies using stop orders, may backtest more profitably with this unusual order situation since the strategy may immediately jump back into a position if the breakout conditions are still met.  This would result in the “phantom” SameEntryExit order and then another order that re-enteres a position based on the other active stop.  For example, if a profit target stop was hit and the entry conditions still exist for the other active stop, then the other active stop order will immediately re-enter the position again, resulting in both the “phantom” order trade and the stop order trade.

Deciding to use or not use this qualification is a matter of personal preference.  I don’t think there is a true “right’ or “wrong” answer in this situation.  Some traders would prefer the possible boost in profit despite the additional “phantom” SameEntryExit trade.  I perfer to keep the strategy behavior and orders clear and simple, even if it trades with a little less profit. If I want a “jump back in” behavior, then I’ll program for it.  But, do your own testing to decide which form suits your own trading style, risk levels and objectives.

Intraday Strategies: Limit Number Of Trades Per Day

Since MultiWalk can take an intraday strategy and apply it against many different symbols and bar intervals, the results can often be surprising and, depending on the strategy, produce a HUGE number of trades (hundreds of thousands) per optimization.  These strategy results will not be tradable and waste both precious run-time and memory resources.  Therefore, decide the maximum number of trades you are willing to have the strategy trade per day and use EntriesToday(date) to limit number of trades on each day. So, for example, place this IF statement around your buy/sell orders:

if ( EntriesToday(date) <= 0 ) then
begin
   buy/sell/etc.
end;

This would limit the trades to one per day.  That might not work if you have (and want) several reversals in one day.  Simply make the trade count per day whatever makes sense for your strategy.

Do Not Use SetExitOnClose

Quite simply, it does not work correctly in some situations and has minimal value when trading real-time. See this article for a better solution.

Avoid Two Critical TradeStation Bugs

There are two crtical TradeStation bugs that we need to avoid in our strategies. It has been years and they still remain unresolved. Kevin and I have both created different workarounds for these bugs. For an explanation and the workarounds, see the followoing article:

https://multiwalk.net/knowledge-base/ts-bugs

Use The Dictionary

TradeStation includes a pretty comprehensive dictionary in the TradeStation Development Environment that describes all the EasyLanguage keywords and functions.

Do Not Use Built-in Variables Value1-99 and Condition1-99

Never use EasyLanguage’s built-in variables Value1-99 or Condition1-99.  From a programming professional point-of-view, these should have never been included in Easylanague.  There are two primary reasons to avoid using these keywords:

Confusion and errors

I ran into situations where a strategy used Value1 and then included a piece of code another strategy that also used Value1.  The result was a very confusing mess trying to determine why the strategy results were incorrect, only to find that the cuprit was Value1 being used for two different reasons.

Lack of meaning

When I am reading someone elese’s code, Value1 has no meaning. What is Value1? What is the purpose of the calculation? But creating and using your own descriptive variable names, such as ‘BreakoutPrice’ or ‘DayCounter’ gives context and meaning to the variable’s usage. SO much better than Value1!

Document Your Code

Always document your code.  Why are you performing a calculation?  Why did you include the logic in your code?  What was the source of your idea?

Describe, describe, describe.  If not for your own sanity when you return to the code months later and wonder why you did something, but also for others if you share the code in the Strategy Factory Club.

Don’t Use Functions Over And Over Again

In the following example, the exact RSI calculation is called twice:

if ( RSI(Close,2) < 20 and MarketPosition <> 1 ) then buy next bar at market;
if ( RSI(Close,2) > 80 and MarketPosition <> -1 ) then sellshort next bar at market;

Since the parameters are the same in both RSI function calls, TradeStation will redundantly call the RSI function and receive the same results for each. This causes unnecessary strain on TS (especially when running many strategies real-time) and creates more processing time (which is especially important when running strategies through MultiWalk that will compound those calculations hundreds and thousands of times!)

Instead, call functions ONE TIME by assigning the result to a variable and then using that variable in your code:

RSIValue = RSI( Close, 2 );

if ( RSIValue < 20 and MarketPosition <> 1 ) then buy next bar at market;
if ( RSIValue > 80 and MarketPosition <> -1 ) then sellshort next bar at market;
Table of Contents