Back

WILR example

I am looking for a way to add a technical indicator, specifically WILR, to my fundamental screener. I was attempting to add it as WILR(x, 14, Resolution.Daily) when I was using the for x in x declaration of the 'fine' screen. 

 

However I kept getting errors; I cannot find much besides scripts that are only using SPY or some other singular symbol for WILR. However, I want to use it to screen my 'universe' for when WILR[-1] < -80 and WILR > -80 

 

Any help is appreciated!

 

Thanks

 

Josh

Update Backtest







0

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.


Hi Josh M ,

Could you please share a backtest with the work you have done so far?

I think that the algorithm should implement a SymbolData helper class with the WilliamsPercentR indicator and a RollingWindow[IndicatorDataPoint]. Since WilliamsPercentR is a BarIndicator, we won't be able to update it only with the data we have in FineFundamental, it requires a Historical data request. However, the design decisions depend on how many symbols the algorithm is filtering in Coarse and Fine.

0

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.


Sorry I'm a noob at python Alexandre Catarino ; just been getting my feet wet the past two days and I think I'm learning rapidly.

 

Thanks for any help!

 

Best, 

 

Josh 

 

 

from QuantConnect.Data.UniverseSelection import *
import math
import numpy as np
import pandas as pd
import scipy as sp
# import statsmodels.api as sm

class CustomSlippageModel:
def GetSlippageApproximation(self, asset, order):
return np.float( asset.Price ) * 0.002

class FundamentalFactorAlgorithm(QCAlgorithm):

def Initialize(self):

self.SetStartDate(2019, 6, 1) #Set Start Date
#self.SetEndDate(2020, 1, 1) #Set Start Date
self.SetCash(100000) #Set Strategy Cash


self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
self.spy = self.AddEquity("SPY", Resolution.Minute).Symbol
self.holding_months = 1
self.num_screener = 100
self.num_stocks = 10
self.formation_days = 200
self.lowmom = False
self.month_count = self.holding_months
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.At(0, 0), Action(self.monthly_rebalance))
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.At(10, 0), Action(self.rebalance))
# rebalance the universe selection once a month
self.rebalence_flag = 0
# make sure to run the universe selection at the start of the algorithm even it's not the manth start
self.first_month_trade_flag = 1
self.trade_flag = 0
self.symbols = None

def CoarseSelectionFunction(self, coarse):
if self.rebalence_flag or self.first_month_trade_flag:
# drop stocks which have no fundamental data or have too low prices
selected = [x for x in coarse if (x.HasFundamentalData) and (float(x.Price) > 5)]
# rank the stocks by dollar volume
filtered = sorted(selected, key=lambda x: x.DollarVolume, reverse=True)

return [ x.Symbol for x in filtered[:500]]
else:
return self.symbols



def FineSelectionFunction(self, fine):
if self.rebalence_flag or self.first_month_trade_flag:
hist = self.History([i.Symbol for i in fine], 1, Resolution.Daily)
filtered_fine = [x for x in fine if (x.ValuationRatios.EVToEBITDA > 0)
and (x.EarningReports.BasicAverageShares.ThreeMonths > 0)
and (WILR[-1](x,14,Resolution.Daily < -80) and WILR(x,14,Resolution.Daily)>-80)
and (WILR[-1](x,14,Resolution.Hourly < -80) and WILR(x,14,Resolution.Hourly)>-80)]
top = sorted(filtered_fine, key = lambda x: x.ValuationRatios.EVToEBITDA, reverse=True)[:self.num_screener]
self.symbols = [x.Symbol for x in top]

self.rebalence_flag = 0
self.first_month_trade_flag = 0
self.trade_flag = 1
return self.symbols
else:
return self.symbols

def OnData(self, data):
pass

def monthly_rebalance(self):
self.rebalence_flag = 1

def rebalance(self):
spy_hist = self.History([self.spy], 120, Resolution.Daily).loc[str(self.spy)]['close']
if self.Securities[self.spy].Price < spy_hist.mean():
for symbol in self.Portfolio.Keys:
if symbol.Value != "TLT":
self.Liquidate()
self.AddEquity("TLT")
self.SetHoldings("TLT", 1)
return

if self.symbols is None: return
chosen_df = self.calc_return(self.symbols)
chosen_df = chosen_df.iloc[:self.num_stocks]

self.existing_pos = 0
add_symbols = []
for symbol in self.Portfolio.Keys:
if symbol.Value == 'SPY': continue
if (symbol.Value not in chosen_df.index):
self.SetHoldings(symbol, 0)
elif (symbol.Value in chosen_df.index):
self.existing_pos += 1

weight = 0.99/len(chosen_df)
for symbol in chosen_df.index:
self.AddEquity(symbol)
self.SetHoldings(symbol, weight)

def calc_return(self, stocks):
hist = self.History(stocks, self.formation_days, Resolution.Daily)
current = self.History(stocks, 1, Resolution.Minute)

self.price = {}
ret = {}

for symbol in stocks:
if str(symbol) in hist.index.levels[0] and str(symbol) in current.index.levels[0]:
self.price[symbol.Value] = list(hist.loc[str(symbol)]['close'])
self.price[symbol.Value].append(current.loc[str(symbol)]['close'][0])

for symbol in self.price.keys():
ret[symbol] = (self.price[symbol][-1] - self.price[symbol][0]) / self.price[symbol][0]
df_ret = pd.DataFrame.from_dict(ret, orient='index')
df_ret.columns = ['return']
sort_return = df_ret.sort_values(by = ['return'], ascending = self.lowmom)

return sort_return

 

0

I was trying to implement it in lines 57 and 58 and it runs, but you are right it doesnt ever seem to update

0

Hello Anyone in the future looking for how I solved my problem:

 

This is how;

 

I began using the 'Algorithm / Alpha Framework'

 

I created a fundamental screener in my universe selection and I created an alpha to create insights based on WILR

 

Here is the module I used 

 

from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *

class WILRAlphaModel(AlphaModel):
def __init__(self):
self.wilr = []
def OnSecuritiesChanged(self, algorithm, changes):
for security in changes.AddedSecurities:
symbol = security.Symbol
self.wilr.append({"symbol":symbol, "indicator":algorithm.WILR(symbol, 14, Resolution.Daily)})
def Update(self, algorithm, data):
ordered = sorted(self.wilr, key=lambda kv: kv["indicator"].Current.Value, reverse=False)
return Insight.Group([Insight.Price(ordered[0]['symbol'], timedelta(1), InsightDirection.Up), Insight.Price(ordered[1]['symbol'], timedelta(1), InsightDirection.Flat) ])

 

0

Hi Josh M ,

Sorry about the wait.
Good to see that you have found a solution, especially one that uses the Algorithm Framework.

Since WilliamsPercentR is a BarIndicator, we need to make a historical data request for all securities if we want to update it inside a universe selection function. It can be quite computationally expensive if we are talking about hundreds of securities. In this case, the best approach, if possible, is to only create the indicators in OnSecuritiesChanged.

Just one note: in the OnSecuritiesChanged of your alpha model, there is no logic to deal with securities removal. In this case, it needs to remove the indicator from the self.wilr list. I prefer using a dictionary keyed by symbol for indicator implementation in alpha models. You can find examples in Lean repo.

1

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.


Update Backtest





0

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.


Loading...

This discussion is closed