Here is the Price/SMA cross-over trading system. It buys shares when the price crosses the Simple Moving Average (SMA) on the up side, and sells these shares when the same cross happens on the down side.
""" Price/SMA cross-over system Parameters: - Period: period of the moving average """ param(Period = 40) if Position.IsFlat: if crossOver(Price, SMA(Period)): enterLong() else: if crossBelow(Price, SMA(Period)): Position.exit()
While this trading system will most certainly not make you rich, it shows the basic structure and what such a system should define: when to enter, and when to exit a position.
The calls to enterLong and Position.exit send buy and sell orders. These orders are then handled by the backtester to simulate the performance of the system on a virtual trading account.
Entry orders allow you to buy or sell shares when the market conditions match the rules of your trading system. To send an entry order, call one of the following functions:
|enterLong||Buy shares to enter a long position.|
|enterShort||Sell shares to enter a short position.|
|enterLongAtLimit||Enter long position at limit parameter.|
|enterShortAtLimit||Enter short position at limit parameter.|
Entry orders only have an effect when no position is opened on the current stock ticker. If a position is already opened, then the call does nothing1).
When you call an entry order, you can set the corresponding limit, stop-loss, take-profit, trailing stop-loss and position size of the trade. Use the following parameters:
|Number of shares to buy or sell.|
|Loss level at which to automatically exit the position.|
|TrailingStop||Draw-down level at which to automatically exit the position.|
|TakeProfit||Profit level at which to automatically exit the position.|
|Limit Parameter 2)||Close-2.0||Limit level at which to automatically enter the position (only for enterLongAtLimit and enterShortAtLimit).|
Here is a sample entry order that makes use of all these parameters:
enterLongAtLimit(Close-2.0, PositionSize=20, StopLoss='5.00%', TrailingStop='10.00%', TakeProfit='10.00%')
The limit price is the only mandatory parameter. This is why it does not need a keyword like PositionSize or TakeProfit.
To close a position, call Position.exit.
If the position is long, then all the shares are sold at the current market price. If the position is short, the shares are bought back.
The Position object contains information about the current position.
if Position.IsFlat: if crossOver(Price, SMA(Period)): enterLong()
The following position properties are available:
|IsFlat||Equals 1 when there is no position on the current ticker.|
|IsShort||Equals 1 when there is a short position on the current ticker.|
|IsLong||Equals 1 when there is a long position on the current ticker.|
|Direction||-1 when short; 0 when flat; 1 when long.|
|TickerId||Identifier of the current stock ticker.|
|NumShares||Number of shares.|
|Commission||Total broker fees paid since the position was opened.|
|EntryPrice||Share price at entry.|
|AverageEntryPrice||Average entry price - useful when there are multiples entries.|
|AverageEntryValue||Average entry price multiplied by number of shares.|
|LastPrice||Last market price.|
|MarketValue||Last market value.|
|TimeLength||Time since entry|
Performances properties are also available:
|RawTotalPL||Total profit or loss, in currency units.|
|NetTotalPL||Total profit or loss, net of commissions.|
|UnrealizedPL||Unrealized P/L, in currency units.|
|RawRealizedPL||Realized P/L, in currency units.|
|PriceGain||Change of price: positive number when favorable / negative when unfavorable.|
|PriceMFE||Max favorable price excursion.|
|PriceMAE||Max adverse price excursion.|
|ValueMFE||Max favorable value excursion.|
|ValueMAE||Max adverse value excursion.|
|PctMFE||Max favorable percentage excursion.|
|PctMAE||Max adverse percentage excursion.|
|PctChange||Percentage change between entry price and last price.|
You can change the size of a position with Position.setNumShares.
Position.setNumShares(Position.NumShares * 2)
The code above generates a buy or sell order which will double the current position.
In the same way, the following methods allow you to modify a position:
|setNumShares||Create a market buy or sell order to reach the new number of shares.|
|setStopLoss||Set a new stop-loss for the current position.|
|setTakeProfit||Set a new take-profit for the current position.|
The Account object contains information about the current performance of the virtual trading account.
Val = Account.Cash
The following performance properties are available:
|Cash||Equity not invested.|
|NetProfit||Profit or loss since the start of the backtest.|
|InitialEquity||Equity at the start of the backtest.|
|PeakEquity||Highest equity since the start of the backtest.|
|LowestEquity||Lowest equity since the start of the backtest.|
|PctDrawdown||Current draw-down as percentage of equity.|
|PctRunnup||Current run-up as percentage of equity.|
The print function displays information in the backtest console3):
if Position.IsFlat: if crossOver(Price, SMA(Period)): print("Entering long position on", Date, "at price", Price) enterLong() else: if crossBelow(Price, SMA(Period)): print("Exiting position on", Date, "at price", Price) Position.exit()