Hi all,
I´m trying get this strategy going but i don´t know what is the problem. It should filter based on three fundamentals but I think that I don´t get the data Needed. (Code in the Appendix)
If possible i would like to also make 2 adjustments:
The filters should be FCFYield (which data i found), FCF/MarketCap and sales/MarketCap.
I´d also like to have minimum Values for the Parameters in case all the market is dropping.
I hope anybody can help. I was searching through all the Website but I didn´t find the answers!
Greetings
Julian
#region imports
from AlgorithmImports import *
from QuantConnect.DataSource import *
from QuantConnect.Data.UniverseSelection import *
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
import math
import numpy as np
import pandas as pd
import scipy as sp
class BasicTemplateAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 1, 1) # Set Start Date
self.SetEndDate(2022, 1, 1) # Set End Date
self.SetCash(100000) # Set Strategy Cash
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
self.SetBenchmark("SPY")
self.num_fine = 30
self.period_sma= 21
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(lambda time:None))
# for quarterly actualisation
self.timedelta = 91
self.NextEntryTime = self.Time
def CoarseSelectionFunction(self, coarse):
return [c.Symbol for c in coarse if c.HasFundamentalData]
def FineSelectionFunction(self, fine):
if self.NextEntryTime==self.Time:
SoartedByMktCap = sorted(fine, key=lambda x: x.MarketCap, reverse=True)[:500] #should return the SP500
fine = [x for x in SoartedByMktCap if x.EarningReports.TotalDividendPerShare.ThreeMonths
and x.ValuationRatios.PriceChange1M
and x.ValuationRatios.FCFYield ]
sortedByfactor1 = sorted(fine, key=lambda x: x.EarningReports.TotalDividendPerShare.ThreeMonths, reverse=True)
sortedByfactor2 = sorted(fine, key=lambda x: x.ValuationRatios.PriceChange1M, reverse=False)
sortedByfactor3 = sorted(fine, key=lambda x: x.ValuationRatios.FCFYield, reverse=True)
stock_dict = {}
for rank1, ele in enumerate(sortedByfactor1):
rank2 = sortedByfactor2.index(ele)
rank3 = sortedByfactor3.index(ele)
stock_dict[ele] = rank1/3 + rank2/3 + rank3/3
#sorting for the best stocks out of all 3 conditions
sorted_stock = sorted(stock_dict.items(),
key=lambda d:d[1], reverse=True)[:self.num_fine]
return [x[0].Symbol for x in sorted_stock]
# sort the top stocks into the long_list and the bottom ones into the short_list
#self.long = [x.Symbol for x in sorted_stock[:self.num_fine]]
#self.short = [x.Symbol for x in sorted_stock[-self.num_fine:]]
#return self.long + self.short
#long_short_list = self.long + self.short
def OnData(self, data):
pass
def rebalance(self):
#if this month the stock are not going to be long/short, liquidate it.
if self.NextEntryTime==self.Time:
for i in self.Portfolio.Invested:
if (i.Invested) and (i not in sorted_stock):
self.Liquidate(i.Symbol)
# Assign each stock equally
if self.NextEntryTime==self.Time:
for i in sorted_stock:
self.SetHoldings(i, 1/self.num_fine)
#for i in self.short:
# self.SetHoldings(i, -0.9/self.num_fine)
self.NextEntryTime = self.Time+self.timedelta #next check in a quarter
Derek Melchin
Hi Julian,
See the attached backtest for a working version of the algorithm above.
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.
Julian Benjamin Griep
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!