VALYNOXSTRATEGY RESEARCH TECHNOLOGY
AlphaPrimeAlphaPrime
ACADEMY / Platforms and export

EasyLanguage vs PowerLanguage: what changes when you move a strategy

Most strategy code compiles on both EasyLanguage and PowerLanguage. The differences sit in a few platform-specific keywords, in how each platform fills orders inside a bar, and in chart settings such as session, time zone and roll method. Make those settings equal first, then compare trade lists tick by tick.

By · Published · updated · Editorial policy

Contents
  1. What is the same and what differs between EasyLanguage and PowerLanguage?
  2. Which keywords and functions behave differently?
  3. How do order fills and intrabar settings differ?
  4. Which data and session settings must match before you compare?
  5. In what order should you migrate a strategy?
  6. How do you test both platforms on the same bars?
  7. Frequently asked questions

What is the same and what differs between EasyLanguage and PowerLanguage?

Most of a strategy moves unchanged between EasyLanguage and PowerLanguage: variables, inputs, conditions, order statements, series references and the common built-in functions compile on both. What changes is a thin layer of platform-specific keywords, the way each platform fills orders inside a bar, and chart settings such as session, time zone and roll method that live outside the code.

EasyLanguage is the programming language of the TradeStation platform. PowerLanguage is the programming language of MultiCharts, and it was designed to accept EasyLanguage code. A series reference is a way of reading a past value, for example the close of one bar ago; both languages write it the same way. Order statements for buying, selling short, exiting, and for market, stop and limit orders also read the same on both platforms.

Think of two cars from the same factory with different dashboards. The engine and the pedals are the same, so you can drive either one straight away. What you must check are the few switches with different labels, and the settings you chose before leaving the garage. For a strategy, the "garage settings" are the chart settings: session template, time zone, intrabar resolution, fill rules and contract rolls. Two platforms with the same code and different chart settings trade a different history, and that is the source of most surprises when people compare backtests.

AlphaPrime (Valynox) exports the same generated strategy as EasyLanguage and as PowerLanguage, among the platforms listed on the platform export page. The rest of this article is the checklist for making the two versions trade the same bars.

Most strategy code moves unchanged between EasyLanguage and PowerLanguage: a long bar of shared code needs no change, a thin layer of platform keywords needs checking, and chart settings sit outside the code Most of the code is shared What moves unchanged, what to check Shared No change Keywords Check Settings Outside the code The code is rarely the problem. So: match settings first.
Most of the code is shared. The differences are a thin layer of platform-specific keywords, plus chart settings that sit outside the code and affect both platforms.

Which keywords and functions behave differently?

Only a short list of items exists on one platform or behaves differently, so the migration starts by searching the code for exactly these items rather than rewriting it. The table below groups them by what you should do.

Code itemEasyLanguagePowerLanguageWhat to do
Order statements (market, stop, limit; next bar, this bar on close)SameSameNo change
Series references and data streams (one bar ago, second data series)SameSameNo change
Inputs, variables, arrays, numbered conditionsSameSameNo change
Print and alert outputSame statements; output goes to the platform's own log windowSame statements; output goes to the PowerLanguage Editor output windowCheck file paths used for printing to disk
File and DLL calls, object-oriented codeObject-oriented EasyLanguage classes and namespaces are TradeStation-onlyDoes not compile object-oriented EasyLanguageReplace with plain functions or remove
Data-feed, symbol, account and portfolio functionsPlatform-specific setPlatform-specific set, including Portfolio Trader keywordsCheck each one; replace with the other platform's equivalent
Intrabar order generationAttribute at the top of the codeSame attribute, plus a signal-level setting in the chartSet the same value on both platforms

The practical method is a search, not a read-through. Open the code and search for the categories in the lower rows: anything that asks the platform about the symbol, the data feed, the account or a portfolio; anything that opens a file or calls a DLL; anything that uses classes or namespaces. Everything the compiler flags will be in those rows. A plain indicator strategy with a moving average, a channel and stop and limit exits usually compiles with no edits at all.

The compiler is your friend here. Compile the code on the target platform before you change anything. The error list tells you exactly which lines need work, and it is shorter than any list you would write by hand.

Only a few code items need edits: orders, series references and inputs need no change, while file paths, object-oriented classes, feed and account functions and the intrabar setting must be checked Only a few rows need edits The compiler flags only these No change Check Orders Series refs Inputs File paths OOP classes Feed, account Intrabar setting The compiler finds the amber rows. So: compile before you edit.
Green rows need no change. Amber rows are where the compiler will flag lines and where a search of the code should start.

How do order fills and intrabar settings differ?

The same order statement can fill at a different price or time on each platform, because each platform has its own intrabar resolution setting, its own default for same-bar versus next-bar entries, and its own rules for stops and limits that fall inside the bar range. These settings must be made equivalent before any result is compared.

Intrabar resolution is how finely the backtest looks inside a bar when it decides where a stop or limit order would have filled. With no intrabar resolution, the platform sees only the open, high, low and close of each bar. If a stop level sits inside that range, the fill is assumed at the stop level, and the order of events inside the bar is unknown: the platform cannot tell whether price hit your stop before or after it hit your target. With a fine intrabar resolution, the platform loads smaller bars (for example one-minute bars under a 30-minute chart) and follows the path of price inside the bar. TradeStation offers this under the name Look-Inside-Bar Back-Testing; the PowerLanguage platform offers it under the name Bar Magnifier. The feature exists on both, but the default state and the chosen resolution are set separately on each platform.

Hypothetical example

A strategy is long one contract of an index future with a stop at 20,000 and a profit target at 20,060. A 30-minute bar opens at 20,030, trades up to 20,065, falls to 19,990 and closes at 20,010. With no intrabar resolution, one platform may record the target hit first and the other the stop hit first, because both levels lie inside the same bar. With one-minute bars loaded inside the 30-minute bar, both platforms see that price reached 20,065 at minute 7 and 19,990 at minute 22, and both record a winning trade at the target. The difference between the two readings is 60 points on one trade (20,060 minus 20,000), from a setting and not from the code.

The second setting is intrabar order generation. Intrabar order generation is a setting that runs the strategy code on every tick instead of once at the close of each bar, so orders can fill inside the current bar. By default, both platforms evaluate the code once at the close of a bar, and a market order placed for the next bar fills at the next bar's open. Both platforms support the same attribute at the top of the code, but the PowerLanguage platform also has a signal-level setting in the chart that can change the behaviour. If one platform runs the code intrabar and the other at bar close, the entry times will differ on almost every trade.

The third item is how a stop or limit is filled when the bar opens beyond its level. Check how each platform handles a stop that is gapped through at the open and a limit order that is only touched, not traded through. Read the documentation of each platform for its exact rule and set both to the more conservative option. AlphaPrime's backtesting evaluates each candidate with fees, slippage and next-bar execution, which is the bar-close-then-next-bar model described above, so a strategy exported from it is easiest to compare when both platforms use next-bar entries.

A hypothetical 30-minute bar contains both the profit target and the stop: with only open, high, low and close the order of hits is unknown, while one-minute bars show the target was reached first Which level was hit first? Hypothetical 30-minute bar, two views OHLC only 1-minute bars Target Unknown Stop Target first Only minute bars show the order. So: match intrabar resolution.
The same stop order, two intrabar resolutions. With only the bar's open, high, low and close the fill is assumed at the stop level; with one-minute bars inside, the fill lands where price actually crossed.

Which data and session settings must match before you compare?

Session template, time zone, bar-building rule, continuous-contract roll method and the maximum bars back are set in the chart, not the code, and each one changes which bars exist, so the table below lists what breaks when they differ.

SettingWhat it changesWhat happens if it differs
Session templateWhich hours of the day are turned into barsOne platform has evening bars, the other does not; daily highs, lows and opens differ
Time zoneThe clock stamped on each barTime-of-day filters fire at different market moments; bars of 30 or 60 minutes may start at a different offset
Bar-building ruleWhere a time bar starts (session open or clock hour) and how volume is countedBar boundaries shift, so every indicator value shifts with them
Continuous-contract rollWhich contract month supplies each bar and whether prices are back-adjustedPrice gaps appear on different dates; stops and channels sit at different levels around rolls
Maximum bars backHow many bars the platform reserves before the first trade can occurTrading starts on a different date, so the first trades do not line up

A session template is the list of opening and closing times the platform uses to turn a day of trading into bars. The session template is the setting that changes the most. A full-session template covers the day and the evening or overnight trading; a day-only template covers the cash-market hours. The same strategy on a full-session chart sees an opening price at the start of the evening session, while on a day-only chart it sees the opening price of the day session. Any rule that uses the day's open, the day's high or an opening range therefore produces different signals on the two charts, even with the same code. Exchanges change session hours from time to time, so take the current hours from the exchange's contract page; the futures market hours tool shows them by exchange and session in your own time zone.

Time zone comes second. Each platform has its own time-zone settings, with choices such as exchange time, local time or GMT. If one chart is in exchange time and the other in your local time, a filter such as "only trade in the first hour" selects a different hour of the market day. Rolls come third: each platform builds continuous contracts with its own roll-date rule and its own choice of back-adjustment, so build both with the same rule, or, where the platform allows importing bar data, export one bar file and load it on both. The backtest data quality article covers gaps, time zones and rolls in more depth.

Maximum bars back is the number of bars the platform holds in reserve so that every indicator in the code has enough history before the first bar on which it may trade. Each platform has its own default and its own way of detecting the number automatically. If one chart reserves 50 bars and the other reserves 200, the second platform starts trading later and the two trade lists are offset from the first day.

One calendar day under two session templates: the full session has evening bars plus day bars, the day-only template has no evening bars, so the day's open, high and low differ Same day, different bars One calendar day, two session templates Full Evening Day Day-only none Day Day's open, high, low differ Different bars, different signals. So: use one session template.
Two session templates, one calendar day. The full-session row produces evening bars that the day-only row never sees, so the day's open, high and low differ and the strategy trades a different history.

In what order should you migrate a strategy?

Follow a fixed order: data first, settings second, code third, comparison last. Doing the comparison first wastes hours hunting differences that come from a session template or a fill setting.

  1. Put the same bars on both platforms. Where the platform allows importing bar data, save the bars from one platform to a text file and load that file on the other; where it does not, use the same data vendor on both and check that the first and last bar of a test day carry the same open, high, low, close and volume on the same timestamps. A shared bar file removes rolls, data-feed differences and bar-building rules from the comparison in one step.
  2. Set the session template and time zone. Use the same session on both charts and display both in the same time zone. Check the first and last bar of one day on each chart; they should carry the same timestamps.
  3. Set intrabar resolution and fill rules. Switch intrabar resolution to the same state and resolution on both platforms, and set intrabar order generation to the same value. Then set the same maximum bars back.
  4. Set commission and slippage. Enter the same per-contract commission and the same slippage per side on both platforms. Without this, a trade list can match perfectly while the equity curves still disagree. The article on trading costs in backtests explains how to choose the values.
  5. Compile and fix flagged keywords. Compile the code on the target platform. Work through the error list using the table in the keyword section above. Change nothing that the compiler did not flag.
  6. Align the trade lists and compare. Export the trade list from both platforms and match trades by entry time, as described in the next section.

If trades differ at step six, go back to step three, not to step five. A difference in entry time on almost every trade points to intrabar order generation. A difference in exit price on stop exits points to intrabar resolution. A difference that starts on a particular date points to a roll or to maximum bars back. Code is the last suspect, because the compiler already caught what the two languages do differently.

Six migration steps in order: bars, session, fills, costs, compile, compare; if the trade lists differ, the loop returns to step 3, the fill settings Settings first, code last Six steps; a mismatch loops back 1 Bars 2 Session 3 Fills 4 Costs 5 Compile 6 Compare Differ? Back to step 3 Most differences are settings. So: fix settings before code.
Settings first, code fixes second, comparison last. When the trade lists differ, the loop returns to the settings, because that is where most differences come from.

How do you test both platforms on the same bars?

Load the same bars on both platforms, run the strategy with the same costs and fill settings, align the two trade lists by entry time, and judge agreement by counting matching trades and measuring price differences in ticks, not by looking at the final equity number alone. AlphaPrime's performance report lists the individual trades of the strategy, which gives you one side of the pairing to align by entry time against each platform's trade list.

A final equity figure hides what you need to know. Two platforms can reach a similar end value with half the trades different, and they can show a large gap in equity because of one trade around a roll date while every other trade matches. Comparing trade by trade tells you which it is. The steps:

  1. Export both trade lists with entry time, direction, entry price, exit time and exit price.
  2. Sort both by entry time and place them side by side in a spreadsheet.
  3. Match each trade on the first platform with the trade on the second platform that has the same entry time and direction. A trade with no partner is an unpaired trade.
  4. For each matched pair, write the entry price difference and the exit price difference in ticks. A tick is the smallest price step of the contract, so this puts every contract on the same scale.
  5. Count the pairs with the same price, the pairs one tick apart and the pairs two or more ticks apart, and list the unpaired trades with their dates.

Hypothetical example

A strategy produces 40 trades on each platform over the same bar file. After matching by entry time, 39 pairs line up and one trade exists on only one platform. Of the 39 pairs, 34 show the same entry and exit price, 3 are one tick apart on the exit price, and 2 are two ticks apart on the exit price. All 5 cases with a price difference are stop exits. The one unpaired trade falls on a contract roll date. The reading is clear: the code behaves the same, intrabar resolution still differs slightly on stop fills, and the roll setting differs on one date. Both are chart settings, and both have a known fix.

What does a good result look like? Nearly every trade matched, most pairs at the same price, and the few price differences explained by one named setting. What does a bad result look like? Many unpaired trades, or differences spread evenly across all exit types, which means the two platforms are not evaluating the code at the same moments. In that case return to intrabar order generation and the session template. The PowerLanguage comparison checklist covers the same alignment method for a strategy moved to the PowerLanguage platform.

Decide your tolerance before you look. A difference of one tick on some stop fills is normal when two platforms use different intrabar data; a difference in which trades exist is not. Write the tolerance down, then run the comparison, so that the result does not change your standard.

Hypothetical comparison of 40 trades on two platforms: 34 matched pairs at the same price, 3 one tick apart, 2 two ticks apart, and 1 trade unpaired Compare trades in ticks Hypothetical: 40 trades, two platforms Same price 34 1 tick 3 2 ticks 2 Unmatched 1 Count matches, not final equity. So: investigate the one unpaired.
Hypothetical example: trades matched by entry time, differences measured in ticks. Most pairs show the same price, a few are one or two ticks apart, and one unpaired trade stands out for investigation.

What this means if you use AlphaPrime: the EasyLanguage version and the PowerLanguage version of a strategy are written from one generated rule set and from a backtest that already uses next-bar execution, fees and slippage, so when the two platforms disagree, the cause is almost always a chart or fill setting, and the checklist above is how you find which one.

Frequently asked questions

Is PowerLanguage the same as EasyLanguage?

PowerLanguage was designed to accept EasyLanguage code, the language of TradeStation, so the two share almost all of their syntax. Variables, inputs, conditions, order statements, series references and the common built-in functions are written the same way. The differences are a small set of platform-specific keywords, object-oriented EasyLanguage classes that only TradeStation compiles, and functions that ask the platform about the symbol, data feed, account or portfolio.

Can I copy EasyLanguage code directly into PowerLanguage?

For most indicator-based strategies, yes: paste the code into the PowerLanguage Editor and compile. The compiler flags any line that uses a TradeStation-only keyword or object-oriented code, and those lines are the only ones to change. The larger work is not in the code but in matching the chart settings, such as session template, intrabar resolution and roll method.

Why do EasyLanguage and PowerLanguage backtests give different results for the same strategy?

The usual causes are chart settings, not code. A different session template produces different bars; a different intrabar resolution fills stops at different prices; a different intrabar order generation setting changes when orders are placed; a different roll rule moves price gaps to other dates. Load the same bars on both platforms and make these settings equal, then compare the trade lists trade by trade.

What is intrabar order generation?

Intrabar order generation is a setting that makes the platform run the strategy code on every tick instead of once at the close of each bar, so orders can be placed and filled inside the current bar. Both EasyLanguage and PowerLanguage support the same attribute at the top of the code, and the PowerLanguage platform also has a signal-level setting in the chart. Set it to the same value on both platforms, or entry times will differ on nearly every trade.