< All Topics

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. I detail several below.  First, let’s start with some extremely important considerations with trade orders.

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 poorly written or unclear trade orders in your strategy.

Entry Orders

Assuming that we are following the Strategy Factory Club protocol and only trading N contracts without any pyramiding/scaling-in or scaling-out methods, then we would only ever have one position active at any time.

In a perfect world, 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;

But TradeStation is far from a perfect world. There are some bug situations, such as this one, that gives incorrect results when we don’t tell TradeStation to only execute the order if a position in the same direction does not exist.

This can easily be avoided by adding MarketPosition qualifiers:

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;

Exit Orders

In a perfect world, 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 real-time orders and cause a “hiccup” in the order flow by placing orders that result in an immediate entry and exit. This causes unnecessary commission and slippage costs as well as potentially confusing orders at the order desk.  I call this the “same entry/exit” issue and write in more detail about it in this article.  Even if a strategy backtests profitably with this odd order behavior, it’s not worth the risk to me to issue unexpected and odd orders when trading.  In other words, keep it simple!

This 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;

 

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/overcoming-two-tradestation-strategy-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