Lesson 14: Your first strategy
Turn a crossover into a strategy with entries, a stop and a target, put real costs in the header, and read the trades the chart draws.
Lesson 14 of 18. A strategy is an indicator that also places orders. The chart does not trade for you: it replays your orders on the bars you can see and shows the trades that would have happened, with the costs you declare.
Orders from a crossover#
strategy "Crossover strategy"
edition = 1
display = price
input fast_length: int = 10, name = "Fast length", min = 1
input slow_length: int = 30, name = "Slow length", min = 2
let fast = tech.ema(close, fast_length)
let slow = tech.ema(close, slow_length)
if tech.crosses_above(fast, slow)
orders.enter("Long", side.long)
if tech.crosses_below(fast, slow)
orders.close("Long")
plot(fast, name = "Fast", color = color.green)
plot(slow, name = "Slow", color = color.red)strategy "Crossover strategy"is the header, in place ofindicator "...".orders.enter("Long", side.long)asks to open a long trade called "Long". The name is how you refer to the trade later.orders.close("Long")asks to close it.- An order is placed when the bar closes, and it fills at the next bar's open. The script cannot buy at the close it has just seen.
A stop and a target#
orders.exit places a stop and a limit for a trade at once. Whichever is reached first closes the trade, and the other is cancelled.
strategy "Crossover with exits"
edition = 1
display = price
input stop_pct: float = 1.0, name = "Stop %", min = 0.1, step = 0.1
input target_pct: float = 2.0, name = "Target %", min = 0.1, step = 0.1
let fast = tech.ema(close, 10)
let slow = tech.ema(close, 30)
if tech.crosses_above(fast, slow)
orders.enter("Long", side.long)
if position.size > 0
let entry = position.avg_price
orders.exit(
"Exit",
"Long",
stop = entry * (1 - stop_pct / 100),
limit = entry * (1 + target_pct / 100),
)
plot(fast, name = "Fast", color = color.green)
plot(slow, name = "Slow", color = color.red)orders.exit(key, entry, stop = ..., limit = ...) belongs to the trade named in entry (here "Long"). It lives only as long as that trade does. position.size is the open size, positive for a long; position.avg_price is the price the trade opened at.
Size and costs in the header#
A result with no costs is flattering. Say what trading costs in the header, in the same place as the size:
strategy "Crossover with costs"
edition = 1
display = price
setup:
capital = 10000
size = sizing.lots(0.1)
fees = fee.per_lot(3.5)
execution:
spread = 20 ticks
slippage = 2 ticks
let fast = tech.ema(close, 10)
let slow = tech.ema(close, 30)
if tech.crosses_above(fast, slow)
orders.enter("Long", side.long)
if tech.crosses_below(fast, slow)
orders.close("Long")
plot(fast, name = "Fast", color = color.green)
plot(slow, name = "Slow", color = color.red)size = sizing.lots(0.1)trades 0.1 lot (a lot is the standard trading size of an instrument). Other ways to say the size aresizing.fixed(n)for units,sizing.equity(p)for a share of the account andsizing.cash(m)for money.spread = 20 ticksandslippage = 2 ticksare in ticks of the symbol (a tick is its smallest price step). The spread is the gap between the buying and the selling price; slippage is the price moving between the order and its fill.fees = fee.per_lot(3.5)charges 3.5 of account money per lot, on every fill.- Every setting is live: you can give one an input, and changing the input changes the next run.
Read the result#
The chart marks each entry with a triangle (the name of the entry beside it) and each exit with a cross, green for a profit and red for a loss, with a dotted line between them. A table in a corner shows the net profit and its percentage, the number of closed trades, the share of them that made money, the profit factor (the money won divided by the money lost), the largest drawdown (the biggest fall of the account from a peak) and the number of trades still open. A Costs row appears when commission or swap was paid. The marks and lines are kept for the newest 500 trades; the table counts all of them. Two inputs on the strategy, Show the trades on the chart and Show the results table, switch the marks and the table off.
In the editor a strategy has one more button, Test: it saves the script and runs it in the Strategy Lab, which tests it over a longer period with more choices of price data and costs. Lesson 15 shows the Lab, and Strategies and the header lists every setting of the header.
Try changing#
- Set
slow_lengthto 50 in the settings of the first program. There are fewer crossings, so the table counts fewer trades. - In the second program, make
target_pctsmaller thanstop_pct, then larger again. Watch how the share of trades that made money and the size of each loss change in the table. - In the third program, raise
spreadto 60 ticks. Every entry fills higher, and the net profit in the table falls. - In the first program, write
side.shortin place ofside.longand usetech.crosses_belowto enter andtech.crosses_aboveto close. The strategy now sells short.
Checkpoint#
- You can write a
strategyheader and open and close a trade withorders.enterandorders.close. - You can protect a trade with
orders.exitand a stop and a target. - You can put the size and the costs in
setup:andexecution:. - You know that an order fills at the next bar's open, and that the chart only simulates the trades.