This is my algorithm:
import quantopian.algorithm as algo
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.data.morningstar import Fundamentals
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.classifiers.morningstar import Sector
import quantopian.optimize as opt
import pandas as pd
import numpy as np
N_ASSETS = 30
SHORT = False
MAX_GROSS_EXPOSURE = 1.0
def initialize(context):
"""
Called once at the start of the algorithm.
"""
algo.schedule_function(
rebalance,
algo.date_rules.month_start(days_offset=10),
algo.time_rules.market_open(hours=1),
)
algo.schedule_function(
record_vars,
algo.date_rules.every_day(),
algo.time_rules.market_close(),
)
algo.attach_pipeline(make_pipeline(), 'pipeline')
set_slippage(slippage.FixedSlippage(spread=0))
set_commission(commission.PerShare(cost=0))
context.rebalance = 0
def make_pipeline():
no_fin_no_utils = ((Sector != 103) & (Sector != 207)) # no financials, no utilites
large_cap = (Fundamentals.market_cap.latest>50e6)
no_low_pe_ratios = (Fundamentals.pe_ratio.latest > 0.5)
no_foreign_companies = ~Fundamentals.is_depositary_receipt.latest
my_universe = QTradableStocksUS() & large_cap & no_fin_no_utils & no_low_pe_ratios & no_foreign_companies
rank = MyFactor().earnings_yield.rank(ascending=False) \
+ MyFactor().return_on_capital.rank(ascending=False)
pipe = Pipeline(
columns={
'rank': rank
},
screen=my_universe
)
return pipe
class MyFactor(CustomFactor):
inputs = [Fundamentals.ebit.latest,
Fundamentals.working_capital.latest,
Fundamentals.net_ppe.latest,
Fundamentals.enterprise_value.latest]
outputs = ['return_on_capital', 'earnings_yield']
window_length = 1
def compute(self, today, asset_ids, out, ebit, net_working_capital, net_fixed_assets, enterprise_value):
out.return_on_capital[:] = ebit/(net_working_capital+net_fixed_assets)
out.earnings_yield[:] = ebit/enterprise_value
def before_trading_start(context, data):
context.output = algo.pipeline_output('pipeline')
context.security_list = context.output.index
def rebalance(context, data):
long_stocks = context.output.nlargest(N_ASSETS, 'rank').index.values
long_weights = pd.Series(index=long_stocks, data=0.3*np.ones(len(long_stocks)))
print(len(context.output.index.values))
if SHORT:
short_stocks = context.output.nsmallest(N_ASSETS, 'rank').index.values
short_weights = pd.Series(index=short_stocks, data=0.3*np.ones(len(short_stocks)))
target_weights = long_weights.append(short_weights)
else:
target_weights = long_weights
objective = opt.TargetWeights(target_weights)
constraints = []
constraints.append(opt.MaxGrossExposure(MAX_GROSS_EXPOSURE))
if get_datetime().month==1:
algo.order_optimal_portfolio(objective, constraints)
context.rebalance = 1
else:
context.rebalance = 0
def record_vars(context, data):
record('rebalance', context.rebalance)
pass
I want to rebalance only every January, that is why I have this code:
if get_datetime().month==1:
algo.order_optimal_portfolio(objective, constraints)
context.rebalance = 1
else:
context.rebalance = 0
However, when I run a full backtest, the algorithm does the rebalancing every January as expected, but it also sells (typically only one stock) in some other month which is not January. I am not sure why?