Documente Academic
Documente Profesional
Documente Cultură
com/BreakoutFutures/Newsletters/Newsletter010
3.htm
The Breakout Bulletin
The following article was originally published in the January 2003 issue of The Breakout
Bulletin.
EasyLanguage Techniques
Many of you are TradeStation users and have no doubt used (or tried to use)
EasyLanguage to program your own trading system. The name notwithstanding,
EasyLanguage can be tricky, even for experienced programmers. So, this
month, I'm going to cover a few EasyLanguage techniques that may be
nonobvious to the uninitiated. I'll first discuss a few basic concepts that are
necessary to understand in order to successfully program a system in
EasyLanguage. Then I'll address a couple of commonly encountered problems
that arise when programming a system. Finally, I'll show you some
EasyLangauge code that accumulates an equity curve using fixed fractional
position sizing. This will illustrate the use of functions.
Some Basics
I don't have the time or space in this format to cover the basics of
EasyLanguage programming or language syntax in any comprehensive way, but
I would like to discuss the concept of program flow and execution. If you've
programmed before in other languages, EasyLanguage probably looks similar to
other procedural languages, such as BASIC, C, Pascal, or Fortran. With respect
to syntax, EasyLanguage is similar in many ways to these other languages.
However, it differs in terms of how the program is executed. Traditional
programming languages, such as the ones mentioned, execute from top to
bottom, then stop at the end. EasyLanguage code, on the other hands, is
executed on each bar of the chart to which it's applied. Confusion can
sometimes arise because variables retain their values from bar to bar. This is
true even within functions. However, the declarations at the top of an
EasyLanguage program are executed only once, on the first bar.
Consider the following code for a make-believe system (or "strategy" in the
latest jargon of TradeStation/EasyLanguage):
Input:
Len1
Len2
(10),
(5);
Var:
A1
B1
C1
(0),
(0),
(0);
A1 = C1 + 1;
B1 = A1 + 1;
C1 = B1 + 1;
{ Comments are written between braces: the following
2 lines generate the entry orders }
If C1 > 10 then Begin
Buy next bar at C + Len1 stop;
In this code, the variable Setup is set to "true" once the condition C < C[2] is found.
Because variables retain their values from one bar to the next, Setup will be "true"
on subsequent bars as well, so the buy order will be generated on subsequent bars
until Setup is reset to false. You always have to be careful when using this technique
to reset the Setup variables so it can be used on the next trade. There are a variety of
ways to do this, depending on the rest of your system code, but one way is shown
above. I've used the built-in function MarketPosition to detect that the long trade has
been entered. Once the trade has been entered, MarketPosition returns 1
(MarketPosition returns 0 for flat, 1 for long, and -1 for short), indicating a long
position is open. This condition is detected by the last "if" statement and used to set
Setup to false. Otherwise, Setup would remain true on all subsequent bars.
Speaking of MarketPosition...
The function MarketPosition, used above, is a very useful function. One problem,
however, is that it only references the current bar. It's sometimes useful to be able to
compare the current market position with the market position on the prior bar. For
example, this can be used to detect that a trade has exited. The common way to
reference the value of a variable or function on prior bars is to use the [] notation.
For example, C[2] is the value of the close two bars ago. If you try to write
MarketPosition[2], however, you'll get an error message. The way around this it to
define your own market position variable:
Var: MarkPos (0);
position }
MarkPos = MarketPosition;
If BarNumber > 1 and MarkPos[1] = 1 and MarkPos <>
MarkPos[1] then
TrailOnL = 0;
{ long trade exited on this bar }
If BarNumber > 1 and MarkPos[1] = -1 and MarkPos <>
MarkPos[1] then
TrailOnS = 0;
{ short trade exited on this
bar }
Variables in EasyLanguage store the values on the prior bars (as far back as the
MaxBarsBack setting), so by setting our MarkPos variable equal to MarketPosition
on each bar, we are effectively storing the past values of MarketPosition. We can
then reference them using the [] notation.
Also note how the MarkPos variable is used to determine that long and short trades
have exited. To detect that a long trade has exited, we check that we were long on
the prior bar (MarkPos[1] = 1) and that our position on the current bar has changed
(MarkPos <> MarkPos[1]). The reverse logic is used to detect that a short trade has
exited. In the example above, taken from an intraday system I was testing, this logic
is used to reset flags that tell the system a trailing stop is active.
A function for fixed fractional position sizing
Of the many ways to size a trade, my favorite is fixed fractional position sizing,
where you risk a certain percentage of your account equity on each trade. For
example, you might risk 2% of your equity on each trade. The risk is usually
determined from the size of the money management stop (e.g., a 12 point stop in the
E-mini S&P represents a risk of $600) or from the largest historical loss for the
system. TradeStation includes a built-in indicator called Strategy Equity that plots
the equity curve for the system currently applied to a chart. However, if you want
the equity curve to represent fixed fractional position sizing, you're on your own in
programming your system to adjust the number of contracts for each trade according
to the fixed fractional equation. The function shown below will do this for you. It
returns the number of contracts for the next trade based on the account equity, trade
risk, and fixed fraction. It accumulates the equity from trade to trade.
Here's the code, preceded by a lengthy comment:
{ User function: NConFF
Calculate the number of contracts for the current trade assuming
a fixed percentage
of account is risked on each trade.
This function implements a fixed fractional approach to position
sizing; see R. Vince, Portfolio
Management Formulas, 1990 for a complete discussion of fixed
fractional trading. The function is
intended to be called by a trading system prior to each trade to
determine the number of contracts
to trade based on the accumulated trading equity, the risk of the
current trade, and the amount to
risk on each trade.
INPUTS:
StEqty: initial account size (starting equity) in dollars.
RiskPer: percentage risk per trade. This is the so-called "fixed
fraction" of fixed
fractional trading.
TrRisk: risk for current trade in dollars; should be positive.
This number can be different
for each trade if desired.
MinNEq1: Set MinNEq1 to either 1 or 0. If equal to 1, the number
of contracts is always
at least equal to 1. In other words, if the number of contracts
would otherwise be equal
to 0 because of a small account size or high trade risk, this
Michael R. Bryant
Breakout Futures
www.BreakoutFutures.com
mrb@BreakoutFutures.com
11/28/00
Copyright 2000
}
Input: StEqty
RiskPer
TrRisk
MinNEq1
Var:
Breakout Futures
(NumericSimple),
(NumericSimple),
(NumericSeries),
(NumericSimple);
NCon
(0),
Equity (0);
{
{
{
{
{ number of contracts }
{ account equity }
TrRisk
NCon
{ risk percentage }
{ =1 --> # contracts at least 1
(0),
(0);
Mike Bryant
Breakout Futures