Hi,
I'm very new to programming and I somehow pieced together a scalping strategy algorithm that 'works'. I would appreciate constructive feedback (coding, strategy etc) from this awesome community.
The strategy is simple:
Double EMA cross - buy when fast crosses above slow; avoid when fast crosses below slow.
def self.Initialize(self):
self.ema = ExponentialMovingAverage("EMA", int(self.GetParameter("EMA")))
self.RegisterIndicator(self.symbol, self.ema)
self.SetWarmup(int(self.GetParameter("EMA")))
self.ema1 = ExponentialMovingAverage("EMA", int(self.GetParameter("EMA1")))
self.RegisterIndicator(self.symbol, self.ema1)
self.SetWarmup(int(self.GetParameter("EMA1")))
def OnData(self, data: Slice):
if not self.Portfolio[self.symbol].Invested:
if self.ema1.Current.Value <= self.ema.Current.Value and \
self.ema.Current.Value < self.Securities[self.symbol].Close:
quantity = self.CalculateOrderQuantity(self.symbol, 1)
self.entryTicket = self.LimitOrder(self.symbol, \
quantity, \
self.Securities[self.symbol].Close, "Entry order")
Thanks!
Derek Melchin
Hi Kristofferson,
Great start. Some things to note:
Best,
Derek Melchin
Want to invest in QuantConnect as we build the Linux of quant finance? Checkout our Wefunder campaign to join the revolution.
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Kristofferson V Tandoc
Hi Derek,
Thank you for your input. I realized what I was doing was wrong, and so I have managed to improve what I previously posted. I will also try to incorporate your comments.
I am a day trader first before learning programming. I have always found the quadruple EMA (QEMA) crossover to be most profitable means of scalping for me and by using algorithmic trading (without selection bias), I'm very curious about its profitability.
I have attempted to code for a QEMA strategy using the algorithm framework but nothing seems to work. Can I get your feedback on how to improve/fix?
I have attached my QEMA crossover strategy using the algorithm framework below.
Thanks again.
Kristofferson V Tandoc
https://www.quantconnect.com/project/13149297
Kristofferson V Tandoc
The universe model seems to work. The alpha model however is a mess.
from universe import QEMAUniverseModel
import pandas as pd
import numpy as np
from AlgorithmImports import *
# endregion
from QuantConnect.Indicators import ExponentialMovingAverage
class QEMAAlphaModel(AlphaModel):
"""
This class emits insights to hold a long (short) position after the chikou line of a
security's Ichimoku Cloud crosses over (under) the top (bottom) of the cloud.
"""
symbol_data_by_symbol = {}
def Update(self, algorithm, data):
"""
Called each time our alpha model receives a new data slice.
Input:
- algorithm
Algorithm instance running the backtest
- data
A data structure for all of an algorithm's data at a single time step
Returns a list of Insights to the portfolio construction model.
"""
self.previous = None
for symbol, symbol_data in self.symbol_data_by_symbol.items():
if not data.ContainsKey(symbol) or data[symbol] is None:
continue
# Update indicator with the latest TradeBar
symbol_data.slow.Update(data[symbol])
if self.previous is not None and self.previous.date() == self.Time.date():
return
close = self.History(self.symbol, 201, Resolution.Daily)["close"]
todayvol = np.std(close[1:201])
yesterdayvol = np.std(close[0:200])
deltavol = (todayvol - yesterdayvol) / todayvol
self.lookback = round(self.lookback * (1 + deltavol))
# Account for upper/lower limit of lockback length
if self.lookback > self.ceiling:
self.lookback = self.ceiling
elif self.lookback < self.floor:
self.lookback = self.floor
def OnSecuritiesChanged(self, algorithm, changes):
"""
Called each time our universe has changed.
Input:
- algorithm
Algorithm instance running the backtest
- changes
The additions and subtractions to the algorithm's security subscriptions
"""
for security in changes.AddedSecurities:
symbol = security.Symbol
self.symbol_data_by_symbol[symbol] = SymbolData(symbol, algorithm)
holdings = self.Portfolio[symbol].Quantity
if holdings <= 0:
# if the fast is greater than the slow, we'll go long
if symbol.Price > self.fast.Current.Value and \
self.fast.Current.Value > self.mid.Current.Value * self.lookback and \
self.mid.Current.Value > self.slow.Current.Value * self.lookback:
self.Log("BUY >> {0}".format(symbol.Close))
self.SetHoldings(symbol, 0.18)
self.stopMarketTicket = self.StopMarketOrder(symbol, -0.18, \
self.initialStopRisk * symbol.Close, "Stop Loss")
if holdings > 0 and self.vfast.Current.Value == self.fast.Current.Value:
self.Log("SELL >> {0}".format(symbol.Price))
self.Liquidate(symbol, "Exit order")
for security in changes.RemovedSecurities:
symbol = security.Symbol
self.symbol_data_by_symbol.pop(security.Symbol, None)
if self.Portfolio[symbol].Invested:
self.Liquidate(symbol, 'Removed from Universe')
# clean up
del self.indicators[security.Symbol]
class SymbolData:
"""
This class is used to store information on each security in the universe. It is
responsible for initializing and warming up the Ichimoku indicator and determining
the position of the chikou line in respect to the cloud.
"""
def __init__(self, symbol, algorithm):
"""
Input:
- symbol
Symbol of the security
- algorithm
Algorithm instance running the backtest
"""
self.entryTicket = None
self.stopMarketTicket = None
self.lookback = 1.0010
self.ceiling, self.floor = 1.0015, 1.0005
self.initialStopRisk = 0.97
self.trailingStopRisk = 0.99
self.previous = None
# Create EMA indicators
self.fast = ExponentialMovingAverage(9)
self.mid = ExponentialMovingAverage(21)
self.slow = ExponentialMovingAverage(55)
self.vfast = ExponentialMovingAverage(5)
# Warm up indicator
# check if indicators are ready
def is_ready(self):
return self.slow.IsReady
# Use the Indicator.Update method to update the time and price of both indicators
def update(self, time, price):
# Use the Update property to get the time and price of indicators
self.fast.Update(time, price)
self.slow.Update(time, price)
Kristofferson V Tandoc
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!