Hi Guys, I am very new to QC and still learning how to work with the platform. I am trying to put together a simple mean reversion buy and sell strategy based on the following but i am struggling with the correct usage of certain functions. I would be grateful someone can put me on the right track.
my main area of challenge is working with OHLC.
Trade conditions;
Buy = open > low.shift(1) < stdev(close.rolling, 15) and open > MA(close.rolling, 8)
Sell = open - high.shift(1) > stdev(close.rolling, 15) and open < MA(close.rolling,
import numpy as np
from datetime import timedelta
from datetime import datetime
import pandas as pd
class IntradayMR_FX(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2015, 1, 1)
#self.SetEndDate(2020, 11, 25)
self.InitCap = 1000000
self.SetCash(self.InitCap)
self.minimumSTD = 15
assets = ["EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCHF","USDJPY","USDCAD"]
self.pairs = [ Pair(self, ticker,self.minimumSTD) for ticker in assets ]
# Risk Management
#---------------------------------------------------------------------------------------
self.positionSizeUSD = 100000 # for 1 million +
self.portval = self.Portfolio.TotalPortfolioValue # total portfolio value for our risk management framework
self.max_dd = 30000 # allocate a % of Capital as Maximum Drawdown
self.waiting_period = None
self.is_invested = None
# Adjust the cash buffer from the default 2.5% to 5% or as required
self.Settings.FreePortfolioValuePercentage = 0.02 # Cash Buffer
self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.05))
#---------------------------------------------------------------------------------------
self.SetWarmUp(30,Resolution.Daily)
def OnData(self, data):
# Risk Management to wait for 15 days after reaching max drawdown
value = self.Portfolio.TotalPortfolioValue
if value > self.portval:
self.portval = value
# Check that at least 15 days (3 weeks) have passed since we last hit our max dd before placing new orders
if self.portval - value > self.max_dd:
self.waiting_period = self.Time
self.Debug("Max DrawDown Reached Wating for 3 weeks")
if (self.waiting_period != None) and (self.Time - self.waiting_period).days < 15:
return
# Store daily data.
for pair in self.pairs:
if not pair.std.IsReady:
return
symbol = pair.symbol
ma = pair.ma.Current.Value
std = pair.std.Current.Value
history = self.History(symbol, 120, Resolution.Daily)
history = history.unstack(level=0).dropna()
#open = history['open', symbol.Value]
#high = history['high', symbol.Value]
#low = history['low', symbol.Value]
#close = history['close', symbol.Value]
open = history.loc[symbol]['open'] ## Open price
high = history.loc[symbol]['high']
low = history.loc[symbol]['low']
close = history.loc[symbol]['close']
if self.Portfolio[symbol].Invested:
if not pair.Investable():
self.Liquidate(symbol, "Not Ready to Invest")
elif close > self.minimumSTD:
self.Liquidate(symbol, "STD not in threshold")
continue
if not pair.Investable():
continue
# Now that we have all values that we need, and the indicator is ready, let's attach the trading mechanism
# if it is not invested, see if there is an entry point
if open - low < std and open > ma and self.Portfolio.MarginRemaining > self.positionSizeUSD:
self.Buy(symbol, self.positionSizeUSD / self.Securities[symbol].Price)
self.Debug('Entering Long')
self.is_invested = 'long'
# if our portfolio is above the upper band, go short
if open - high > std and open < ma and self.Portfolio.MarginRemaining > self.positionSizeUSD:
self.Sell(symbol, -(self.positionSizeUSD / self.Securities[symbol].Price))
self.Debug('Entering Short')
self.is_invested = 'short'
class Pair:
def __init__(self, algorithm, ticker,minimumSTD):
self.symbol = algorithm.AddForex(ticker, Resolution.Daily, Market.Oanda).Symbol
self.ma = algorithm.SMA(self.symbol, 8, Resolution.Daily)
self.std = algorithm.STD(self.symbol, 15, Resolution.Daily)
self.minimumSTD = minimumSTD
def Investable(self):
return (self.std.Current.Value <= self.minimumSTD)
Thanks AndyG
Vladimir
Andygsax,
Try this slightly modified version of your strategy.
If you are satisfied with my answer, please accept it.
.ekz.
Quick note: calling history multiple times in the OnData handler might be a performance drag. Consider using Rolling windows, since the data is already there.
Andygsax
Vladimir and .ekz.
Thank you so much for taking time to help out, your suggestion is close but missing some part of the logic. Below is what i have on my python ide which works. i just seem to be struggling with or getting my head around slicing the OHLC and converting the same to the QC. The python file looks like this if it helps…
Varad Kabade
Hi Andygsax
The above algorithm is trying to reference a pandas data frame as a decimal when getting OHLC data.
To get the current OHLC data inside the OnData method please use:
Note that all the indicators need to be warmed up before they are ready to use. To check if an indicator is warmed up, we can use the IsReady property of an indicator object:
To make sure indicators are ready at the start of backtesting we can manually warm them up using historical data requests. Refer to the following docs for more information.
Best,
Varad Kabade
Vladimir
Andygsax,
If you still struggling with the correct usage of certain functions here is an efficient way to get Yesterday High and Yesterday Low without using History or Rolling windows.
If you are satisfied with my answer, please accept it.
Andygsax
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!