def my_rebalance_opt(context, data): """ Our monthly rebalancing routine """ # First update the stock universe. context.output = pipeline_output('investment_universe') context.security_list = context.output.index # Get data hist_window = max(context.momentum_window, context.momentum_window2) + context.exclude_days hist = data.history(context.security_list, "close", hist_window, "1d") data_end = -1 * context.exclude_days # exclude most recent data momentum1_start = -1 * (context.momentum_window + context.exclude_days) momentum_hist1 = hist[momentum1_start:data_end] momentum2_start = -1 * (context.momentum_window2 + context.exclude_days) momentum_hist2 = hist[momentum2_start:data_end] # Calculate momentum scores for all stocks. momentum_list = momentum_hist1.apply(slope) # Mom Window 1 momentum_list2 = momentum_hist2.apply(slope) # Mom Window 2 # Combine the lists and make average momentum_concat = pd.concat((momentum_list, momentum_list2)) mom_by_row = momentum_concat.groupby(momentum_concat.index) mom_means = mom_by_row.mean() # Calculate inverse volatility, for position size. inv_vola_table = hist.apply(inv_vola_calc) alpha = (mom_means * inv_vola_table).dropna() objective = opt.MaximizeAlpha(alpha) constrain_gross_leverage = opt.MaxGrossLeverage(MAX_GROSS_LEVERAGE) constrain_pos_size = opt.PositionConcentration.with_equal_bounds( -MAX_SHORT_POSITION_SIZE, MAX_LONG_POSITION_SIZE, ) market_neutral = opt.DollarNeutral() sector_neutral = opt.NetPartitionExposure.with_equal_bounds( labels=context.output.sector, min=-MAX_SHORT_SECTOR_SIZE, max=MAX_LONG_SECTOR_SIZE, ) order_optimal_portfolio(objective, constraints=[ constrain_gross_leverage, constrain_pos_size, market_neutral, sector_neutral ], universe=context.security_list)
def rebalance(context, data): ### Optimize API pipeline_data = context.pipeline_data ### Extract from pipeline any specific risk factors you want # to neutralize that you have already calculated risk_factor_exposures = pd.DataFrame( {'market_beta': pipeline_data.market_beta.fillna(1.0)}) # We fill in any missing factor values with a market beta of 1.0. # We do this rather than simply dropping the values because we have # want to err on the side of caution. We don't want to exclude # a security just because it's missing a calculated market beta, # so we assume any missing values have full exposure to the market. ### Here we define our objective for the Optimize API. We have # selected MaximizeAlpha because we believe our combined factor # ranking to be proportional to expected returns. This routine # will optimize the expected return of our algorithm, going # long on the highest expected return and short on the lowest. objective = opt.MaximizeAlpha(pipeline_data.combined_rank) ### Define the list of constraints constraints = [] # Constrain our maximum gross leverage constraints.append(opt.MaxGrossLeverage(MAX_GROSS_LEVERAGE)) # Require our algorithm to remain dollar neutral constraints.append(opt.DollarNeutral()) # Add a sector neutrality constraint using the sector # classifier that we included in pipeline constraints.append( opt.NetPartitionExposure.with_equal_bounds( labels=pipeline_data.sector, min=-MAX_SECTOR_EXPOSURE, max=MAX_SECTOR_EXPOSURE, )) # Take the risk factors that you extracted above and # list your desired max/min exposures to them - # Here we selection +/- 0.01 to remain near 0. neutralize_risk_factors = opt.WeightedExposure( loadings=risk_factor_exposures, min_exposures={'market_beta': -MAX_BETA_EXPOSURE}, max_exposures={'market_beta': MAX_BETA_EXPOSURE}) constraints.append(neutralize_risk_factors) # With this constraint we enforce that no position can make up # greater than MAX_SHORT_POSITION_SIZE on the short side and # no greater than MAX_LONG_POSITION_SIZE on the long side. This # ensures that we do not overly concentrate our portfolio in # one security or a small subset of securities. constraints.append( opt.PositionConcentration.with_equal_bounds( min=-MAX_SHORT_POSITION_SIZE, max=MAX_LONG_POSITION_SIZE)) ### Put together all the pieces we defined above by passing # them into the order_optimal_portfolio function. This handles # all of our ordering logic, assigning appropriate weights # to the securities in our universe to maximize our alpha with # respect to the given constraints. order_optimal_portfolio(objective=objective, constraints=constraints)
def do_portfolio_construction(context, data): pipeline_data = context.pipeline_data todays_universe = pipeline_data.index # Objective # --------- # For our objective, we simply use our naive ranks as an alpha coefficient # and try to maximize that alpha. # # This is a **very** naive model. Since our alphas are so widely spread out, # we should expect to always allocate the maximum amount of long/short # capital to assets with high/low ranks. # # A more sophisticated model would apply some re-scaling here to try to generate # more meaningful predictions of future returns. objective = opt.MaximizeAlpha(pipeline_data.alpha) # Constraints # ----------- # Constrain our gross leverage to 1.0 or less. This means that the absolute # value of our long and short positions should not exceed the value of our # portfolio. constrain_gross_leverage = opt.MaxGrossLeverage(MAX_GROSS_LEVERAGE) # Constrain individual position size to no more than a fixed percentage # of our portfolio. Because our alphas are so widely distributed, we # should expect to end up hitting this max for every stock in our universe. constrain_pos_size = opt.PositionConcentration.with_equal_bounds( -MAX_SHORT_POSITION_SIZE, MAX_LONG_POSITION_SIZE, ) # Constrain ourselves to allocate the same amount of capital to # long and short positions. market_neutral = opt.DollarNeutral() # Constrain ourselve to have a net leverage of 0.0 in each sector. sector_neutral = opt.NetPartitionExposure.with_equal_bounds( labels=pipeline_data.sector, min=-0.0001, max=0.0001, ) # Run the optimization. This will calculate new portfolio weights and # manage moving our portfolio toward the target. algo.order_optimal_portfolio( objective=objective, constraints=[ constrain_gross_leverage, constrain_pos_size, market_neutral, sector_neutral, ], universe=todays_universe, )
def my_rebalance(context, data): """ Execute orders according to our schedule_function() timing. """ risk_model_factors = context.risk_factors risk_model_factors = risk_model_factors.join(context.predicted_probs, how='right').dropna() predictions = risk_model_factors.ML # Filter out stocks that can not be traded predictions = predictions.loc[data.can_trade(predictions.index)] # Select top and bottom N stocks predictions = pd.concat([ predictions.nlargest(N_STOCKS_TO_TRADE // 2), predictions.nsmallest(N_STOCKS_TO_TRADE // 2) ]) todays_universe = predictions.index predictions -= 0.5 # predictions are probabilities ranging from 0 to 1 # Setup Optimization Objective objective = opt.MaximizeAlpha(predictions) # Setup Optimization Constraints constrain_gross_leverage = opt.MaxGrossLeverage(1.0) constrain_pos_size = opt.PositionConcentration.with_equal_bounds(-.02, .02) market_neutral = opt.DollarNeutral() # TypeError: cannot do label indexing on <class 'pandas.indexes.base.Index'> with these indexers [nan] of <type 'float'> sector_neutral = opt.NetPartitionExposure.with_equal_bounds( labels=context.risk_factors.Sector.dropna(), min=-0.0001, max=0.0001, ) # Run the optimization. This will calculate new portfolio weights and # manage moving our portfolio toward the target. order_optimal_portfolio( objective=objective, constraints=[ constrain_gross_leverage, constrain_pos_size, market_neutral, sector_neutral, ], universe=todays_universe, )
def do_portfolio_construction(context, data): pipeline_data = context.pipeline_data todays_universe = pipeline_data.index # Objective here was to maximise alpha which is # our factor defined in the pipeline. objective = opt.MaximizeAlpha(pipeline_data.alpha) # Constrain our gross leverage to 1.0 or less. # This means that the absolute value of our long and short positions # should not exceed the value of our portfolio. constrain_gross_leverage = opt.MaxGrossLeverage(MAX_GROSS_LEVERAGE) # Constrain individual position size to no more than a fixed percentage # of our portfolio. constrain_pos_size = opt.PositionConcentration.with_equal_bounds( -MAX_SHORT_POSITION_SIZE, MAX_LONG_POSITION_SIZE, ) # Constrain ourselves to allocate the same amount of capital to # long and short positions. Not used in the simulations in this work. market_neutral = opt.DollarNeutral() # Constrain the maximum average exposure # to individual sectors to -10% - 10%. sector_neutral = opt.NetPartitionExposure.with_equal_bounds( labels=pipeline_data.sector, min=-0.10, max=0.10, ) # Run the optimization. # This will calculate new portfolio weights and # manage moving our portfolio toward the target. algo.order_optimal_portfolio( objective=objective, constraints=[ constrain_gross_leverage, constrain_pos_size, # market_neutral, ---> not used in the study. sector_neutral, ], universe=todays_universe, )