My first algo: ema crossing and request for help

Hi all,
This is my first attempt to write an algorithm based on my own (and many others) trading strategies: The idea is to buy when the fast ema crosses the slow ema and the stock is bullish (price higher than a slow sma, e.g., 100 sma); and to short the stock when the conditions are the exact opposite.
I only use indexes (the ones that I remember anyway) in order to ensure high volume and interest.

As you see from the results, the drawdown is huge which I think the reason is that in real trading, the transactions are performed directly after the crossing. In order to do this, I need the ema values for the previous days. I however, have no idea how to access the ema values or price values for past days and only use the current price or ema values. Can anyone help me here and explains how to do that? I would really appreciate that.

In addition, when checking the transactions, I could not see that a shorting was taking place. Am I doing something wrong here?

Regards

61
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
"""
This strategy is meant to buy when the emas cross each other and the price is over the 100 sma.

It then backs off (or shorts) of the positions when the price drops below the 100-day SMA
and the emas cross on the other side.
"""

sma = ta.SMA(timeperiod=100)
ema = ta.EMA(timeperiod=10)
ema_5 = ta.EMA(timeperiod=5)

def initialize(context):
context.stocks = {sid(8554), sid(19920), sid(21785), sid(23921), sid(32381), sid(24705), sid(12915), sid(33655), sid(33748)
, sid(19656), sid(21555), sid(32275), sid(25593), sid(22445), sid(21652), sid(28074), sid(26807), sid(28320)
, sid(22463), sid(19655) , sid(32279)}

context.min_notional = -1000000.0
context.max_notional = 1000000.0

# Will be called on every trade event for the securities you specify.
def handle_data(context, data):

for stock in context.stocks:
sma_data = sma(data)
stock_sma = sma_data[stock]
ema_data = ema(data)
ema5_data = ema_5(data)
stock_ema = ema_data[stock]
stock_ema5 = ema5_data[stock]

price = data[stock].price
shares = context.portfolio.positions[stock].amount
notional = context.portfolio.positions[stock].amount * data[stock].close_price

if stock_sma < data[stock].close_price:
if stock_ema < stock_ema5:
if data[stock].close_price > stock_ema and notional < context.max_notional:
if  data[stock].close_price > stock_ema5 and notional < context.max_notional:
order(stock, +100)
log.info("SMA100 is at " + str(stock_sma) + ", price is at " + str(price) + " buying 100 shares")

if stock_sma > data[stock].close_price:
if stock_ema > stock_ema5:
if data[stock].close_price < stock_ema and shares >= 100:
if data[stock].close_price < stock_ema5 and shares > 100:
order(stock, -100)
log.info("SMA100 is at " + str(stock_sma) + ", price is at " + str(price) + ", selling 100 shares")


This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.
4 responses

Peter Cawthron,

Hello Omar,

Sorry - the code had a major defect. I'll post it again once that is resolved!

P.

Hello Peter,
Thank you so very much for your help. Your idea about creating a queue of length 2 is actually a good solution. I wouldn't have thought about it myself. I will also experiment with it while waiting for your answer.
/Omar

Hello Peter,
Thank you so very much for your help. Your idea about creating a queue of length 2 is actually a good solution. I wouldn't have thought about it myself. I will also experiment with it while waiting for your answer.
/Omar