Skip to main content
In this tutorial we write a strategy: it goes long when a fast moving average crosses above a slow one and closes the position when the fast one crosses back below. A strategy runs on the chart’s history and records the trades it would have made. The orders are simulated on an account inside the script engine; nothing is sent to a broker. Every step is a whole script: replace what is in the editor, and check it.
1

declare a strategy and draw the averages

A strategy declares itself with strategy(...) instead of indicator(...). A script has exactly one of the two. It may plot like an indicator.
GoCharting is a charting and analytics tool. This is not investment advice. Trading and investing carry a high risk of loss and are not suitable for everyone. You can lose some or all of your money.
These results are based on simulated or hypothetical performance that has inherent limitations. They do not represent actual trading and were not executed, and may under- or over-compensate for market factors such as liquidity. Simulated results are designed with the benefit of hindsight. No representation is made that any account will or is likely to achieve similar profits or losses.
Two lines are drawn over the price bars. No orders are placed yet.
2

enter when the fast average crosses above

talib.crossover(fast, slow) is true on the bar where fast moves from at or below slow to above it. strategy.entry(id, direction) places an order to open a position: id names it, and direction is strategy.long or strategy.short.
The strategy now opens a long position at each upward cross. A market order placed on a bar is filled at the start of the next bar, at its open, so the entry price is the next bar’s open and not the close that triggered it. While a long position is open a second strategy.entry in the same direction is ignored, because pyramiding defaults to 1.
3

close when it crosses back

strategy.close(id) closes the position opened under that id. talib.crossunder(fast, slow) is true where fast moves from at or above slow to below it.
Each long trade now ends at the next downward cross. To reverse into a short instead of going flat, call strategy.entry("Short", strategy.short) there: an entry against an open position closes it and opens the new one.
4

set up the account

The account is set in strategy(...). Every argument is a fixed value, not a calculation. The ones used most:strategy.fixed is a constant. There is no strategy.cash or strategy.percent_of_equity:
The compiler says: Namespace strategy has no variable percent_of_equity. To size by equity, pass the quantity to the order: strategy.entry("Long", strategy.long, qty=strategy.equity * 0.1 / close).
5

show the position and the result

strategy.position_size is the signed size of the open position (positive long, negative short, zero flat). We shade the background while long and give each order a comment. The trade list, equity and totals appear in the strategy’s results (see Reading a strategy’s results); strategy.netprofit, strategy.equity and the other strategy.* variables are readable in the script too.

What we built

A long-only crossover strategy with inputs for both lengths, a 10,000 account, a 0.05 percent commission on each fill, and a green background while a position is open. The orders are simulated; to be told when a signal appears, use an alert (see Alert on your own condition).

Next

Strategies and backtesting

how a strategy runs and what it can and cannot do.

Orders and positions

limit and stop orders, strategy.exit, strategy.order.

Reading a strategy's results

the trade list and the strategy.* variables.