In this lesson, we will have a closer look at Simple Strategies, they allow focusing on the logic without having to worry much about the trading logic.
Trading is going to be executed using the Machina Settings and the strategy only need to return a signal on each new candle: either BUY, SELL or HOLD.
Let’s have a close look at this first example (Can be downloaded at the end of the article):
import sys, talib, requests, json, numpy, base64, json, enum, datetime, array, math
#Basic SMAs Xing (Simple Strategy)
STRAT_NAME = ‘Basic SMAs Xing (Simple Strategy)’
STRAT_TYPE = mtCommon.SimpleStrategy
VERSION = ‘1’
NUM_CANDLES = 25
SMA_FAST = ‘SMA Fast’
SMA_SLOW = ‘SMA Slow’
# Build up parameters to send to MT
_mt.addNumericParameter(SMA_FAST, 12, True)# This parameter will override the NUM_CANDLES value if it is higher
_mt.addNumericParameter(SMA_SLOW, 18, True)# This parameter will override the NUM_CANDLES value if it is higher
# Per market methods – Execution triggered per market (as per machina configuration)
_mt.logInfoP(‘onInit called [‘ + STRAT_NAME + ‘, v’ + VERSION + ‘]’)
def onTick(currentDate, candles, config):
# _mt.logInfo(‘onTick called | Market: ‘ + config.MARKET + ‘, currentDate: ‘ + str(currentDate) + ‘, ‘ + str(len(candles.C)) + ‘ candles available’, “blue”)
# Import Parameters
fastPeriod = int(_mt.getParameter(SMA_FAST))
slowPeriod = int(_mt.getParameter(SMA_SLOW))
# Calc Moving Averages
# maType = 0 = SMA
# candles.C = Close Values
fastValues = talib.func.MA(candles.C, timeperiod=fastPeriod, matype=0)
slowValues = talib.func.MA(candles.C, timeperiod=slowPeriod, matype=0)
# we only use the last value
fastValue = fastValues[-1]
slowValue = slowValues[-1]
# Render on Chart
_mt.plotPoint(‘fast’, fastValue, ‘#C70039’)
_mt.plotPoint(‘slow’, slowValue, ‘#3700C7’)
# Trading Logic
if fastValue > slowValue:
It starts by the import statements, we need talib
for having access to technical analysis, numpy
for dealing with numbers and a few other basic python libs.
We also import mtCommon
which is required for any Strategy.
Then we declare the required constants: STRAT_NAME
can be either mtCommon.SimpleStrategy (1)
or mtCommon.TradingStrategy (2)
and defines if the strategy is a Simple Strategy (producing signals) or a Trading Strategy (producing orders).
If we want to use more than 25 candles during our calculations, we’ll need to increase the NUM_CANDLES
In the onDefParams
method, we define 2 parameters for the user: SMA Fast
and SMA Slow
method is the most interesting one, it is being called on each “Tick” so every time we receive a new candle and it’s where we do our calculation to decide if the strategy should Buy, Sell or Hold.
First we retrieve the values for our parameters using the _mt.getParameter
Then we calculate the Moving Averages
using talib’s MA method: We provide the candles we have, the desired period as well as the type of Moving Average (in our case SMA corresponding to maType 0).
After this, we render the two Moving Averages on the chart using the _mt.plotPoint
And finally we have the logic that will determine if we issue a BUY or SELL signal relying on the Simple Strategy helpers:
Now let’s try to run this to see what happens, we can see the our 2 parameters which we have defined (SMA Fast + Slow).
Once the backtest is completed, we get the following:
What we observe here is that each time we have several Buy Orders but only a single Sell Order. This is due to our Machina Configuration.
To change that, we can go to the configuration for our Machina and change the Buy Settings
to have only 1 Max Open Position Per Coin
Running the backtest again will give the following behaviour where we can see every time a Buy Order followed by a Sell Order:
It’s definitely not recommended to run this strategy with real assets but you can use this strategy as a boilerplate for getting started and having fun with MachinaTrader!