You can then define an initial portfolio. In the following example linearly increasing weights are applied to the 20 large cap stocks:
company_names = [f"{sig.obj.get(x).company_name}{n}"for n, x inenumerate(universe)]pf_ts = pd.Series(index=company_names, data=np.linspace(0.1,1,20))pf_ts = pf_ts / pf_ts.sum()pf_ts.plot(kind='bar', title='Initial Portfolio Allocations %');
To create the reinvestment strategies and calculate their corresponding returns:
rs = [get_single_stock_strategy(ss)for ss in universe]universe_mapping ={ss:f'{ss} REINV STRATEGY'for ss in universe}single_stock_returns ={s.name: s.history().pct_change().dropna()for s in rs}pf_ts.index = universe_mapping.values()
Fit factor exposures
To calculate your static portfolio's exposure to the Fama-French factors—market risk, small minus big, high minus low—fit these factors to your portfolio's stock returns:
The factor exposure object is used to provide information to an optimiser. This optimisation is specified by an OptimizationProblem object and performed using the Optimizer class.
Interactive optimiser
Use the interactive optimisation interface to construct an optimisation problem and explore the results:
The interface allows you to test different static optimisations and retrieve the GUI's current active OptimizationProblem object:
problem = int_port_opt.optimization_problem
Defining an optimisation
A problem can also be defined by code. The following example sets up an optimization problem, defining objectives and bounds (also known as constraints):
# Create an optimization problemproblem = sig.OptimizationProblem()# Add an objective to minimize the exposure to the market factorproblem.set_optimizer_objective(TermTypes.EXPOSURE, element='MKT', metric=MetricTypes.SQUARE, value=-0.0001)# Add an objective to minimize the varianceproblem.set_optimizer_objective(TermTypes.VARIANCE, element='FULL', metric=MetricTypes.VARIANCE, value=-1)# Add a constraint to go long onlyproblem.set_optimizer_bounds(TermTypes.WEIGHT, element='ALL', metric=MetricTypes.LINEAR, min_value=0)# Add a constraint for 100% exposureproblem.set_optimizer_bounds(TermTypes.WEIGHT, element='SUM_', metric=MetricTypes.LINEAR, min_value=1, max_value=1)
Running the problem with the Optimizer returns and plots the new optimized weights:
Once defined, the optimisation can be run on a rolling basis as part of a SignalStrategy or EquityFactorBasket using the factor_optimized_allocations allocation function.
Define a monthly rebalance schedule and construct an equally weighted portfolio by applying a single unit of weights to each reinvestment strategy in your signal DataFrame:
rebal_dates = sig.SchedulePeriodic( START_DATE, env.asofdate,'NYSE(T) CALENDAR', frequency='EOM').all_data_dates()signal_df = pd.DataFrame({s.name: 1for s in rs}, index=rebal_dates)signal_df.head()
Then define your optimisation to be run on each rebalance date as part of your SignalStrategy: