def test_TLH(self): # out of currently held lots identify lots losing above some treshold - calculate lost weight - as PCT of portfolio value # set max constraint for those lots to PCT - as if we had sold those lots completely pp_type = self.goal.portfolio_set.portfolio_provider.type if pp_type == constants.PORTFOLIO_PROVIDER_TYPE_AON or pp_type == constants.PORTFOLIO_PROVIDER_TYPE_KRANE or \ pp_type == constants.PORTFOLIO_PROVIDER_TYPE_LEE: self.assertTrue(True) return self.goal.account.tax_loss_harvesting_consent = True self.goal.account.save() GoalMetricFactory.create(group=self.goal_settings.metric_group, feature=self.equity, type=GoalMetric.METRIC_TYPE_RISK_SCORE, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, rebalance_thr=0.5, configured_val=0.5) self.t4.unit_price = 10 self.t4.save() weights, instruments, reason = rebalance(self.goal, self.idata, self.data_provider, self.execution_provider) self.assertAlmostEqual(weights[4], 0) self.assertTrue(weights[5] > 0) weight_5 = weights[5] self.goal.account.tax_loss_harvesting_consent = False self.goal.account.save() weights, instruments, reason = rebalance(self.goal, self.idata, self.data_provider, self.execution_provider) self.assertNotAlmostEqual(weights[4], 0) self.assertNotAlmostEqual(weights[5], weight_5)
def test_do_not_rebuy_within_30_days(self): # finish test GoalMetricFactory.create( group=self.goal_settings.metric_group, feature=self.equity, type=GoalMetric.METRIC_TYPE_RISK_SCORE, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, rebalance_thr=0.5, configured_val=0.5) weights, instruments, reason = rebalance(self.goal, self.idata, self.data_provider, self.execution_provider) executed = datetime(year=2016, month=5, day=15) for i in range(3, 5): Fixture1.create_execution_details(self.goal, self.tickers[i], -self.quantities[i], self.tickers[i].unit_price, executed) self.goal.cash_balance += self.tickers[i].unit_price * abs( self.quantities[i]) weights, instruments, reason = rebalance(self.goal, self.idata, self.data_provider, self.execution_provider) self.assertAlmostEqual(weights[4], 0)
def metric_group2(cls): g, c = GoalMetricGroup.objects.get_or_create( type=GoalMetricGroup.TYPE_PRESET, name='metricgroup2') # A metric group isn't valid without a risk score, and we only want to create the metric if the group was # newly created. if c: GoalMetricFactory.create(group=g, configured_val=MINIMUM_RISK) return g
def test_perturbate_risk(self): GoalMetricFactory.create(group=self.goal_settings.metric_group, feature=self.equity, type=GoalMetric.METRIC_TYPE_RISK_SCORE, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, rebalance_thr=0.5, configured_val=0.5) lots = get_tax_lots(self.goal) weights = get_weights(lots, self.goal.available_balance) #risk = process_risk(weights=weights, goal=self.goal, idata=idata, data_provider=data_provider, execution_provider=execution_provider) #weights = perturbate_risk(goal=self.goal) self.assertTrue(True)
def test_calculate_portfolio_old(self): fund0 = TickerFactory.create(symbol='IAGG') fund1 = TickerFactory.create(symbol='ITOT') fund5 = TickerFactory.create(symbol='GRFXX') fund2 = TickerFactory.create(symbol='VEA') fund0 = TickerFactory.create(symbol='IPO') fund3 = TickerFactory.create(symbol='EEM') fund4 = TickerFactory.create(symbol='AGG') AssetFeatureValueFactory.create( assets=[fund1, fund2, fund3, fund4, fund5]) ps1 = PortfolioSetFactory \ .create(asset_classes=[fund1.asset_class, fund2.asset_class, fund3.asset_class, fund4.asset_class, fund5.asset_class]) # Create a settings object with a metric for a feature with no instruments in the current portfolio set. feature = AssetFeatureValueFactory.create() settings = GoalSettingFactory.create() risk_metric = GoalMetricFactory.create(group=settings.metric_group) mix_metric = GoalMetricFactory.create( group=settings.metric_group, type=GoalMetric.METRIC_TYPE_PORTFOLIO_MIX, feature=feature, comparison=GoalMetric.METRIC_COMPARISON_MAXIMUM, configured_val=.3) goal = GoalFactory.create(selected_settings=settings, portfolio_set=ps1) # The below fund has the desired feature, but is not in the goal's portfolio set. feature.assets.add(fund1) # Create some instrument data for the two assets self.m_scale = MarkowitzScaleFactory.create() # populate the data needed for the prediction # We need at least 500 days as the cycles go up to 70 days and we need at least 7 cycles. populate_prices(500, asof=mocked_now.date()) populate_cycle_obs(500, asof=mocked_now.date()) populate_cycle_prediction(asof=mocked_now.date()) data_provider = DataProviderDjango() execution_provider = ExecutionProviderDjango() idata = build_instruments(data_provider) result = calculate_portfolio_old(settings=settings, data_provider=data_provider, execution_provider=execution_provider, idata=idata) self.assertTrue(True)
def test_calculate_portfolio(self): # TODO # constraints -> limit them -> maximum minimum value of 5%, maximum max value of 95% asset_class1 = AssetClassFactory.create(name='US_TOTAL_BOND_MARKET') asset_class2 = AssetClassFactory.create(name='HEDGE_FUNDS') fund0 = TickerFactory.create(symbol='IAGG', asset_class=asset_class1) fund0 = TickerFactory.create(symbol='GRFXX', asset_class=asset_class1) fund1 = TickerFactory.create(symbol='ITOT', asset_class=asset_class2) fund0 = TickerFactory.create(symbol='IPO') fund0 = TickerFactory.create(symbol='AGG', asset_class=asset_class1) fund6 = TickerFactory.create(symbol='rest') ps1 = PortfolioSetFactory \ .create(asset_classes=[asset_class1, asset_class2, fund6.asset_class]) feature = AssetFeatureValueFactory.create() feature.assets.add(fund6) settings = GoalSettingFactory.create() risk_metric = GoalMetricFactory.create( group=settings.metric_group, type=GoalMetric.METRIC_TYPE_RISK_SCORE) mix_metric = GoalMetricFactory.create( group=settings.metric_group, type=GoalMetric.METRIC_TYPE_PORTFOLIO_MIX, feature=feature, comparison=GoalMetric.METRIC_COMPARISON_MINIMUM, configured_val=0.5) goal = GoalFactory.create(selected_settings=settings, portfolio_set=ps1) # Create some instrument data for the two assets self.m_scale = MarkowitzScaleFactory.create() populate_prices(500, asof=mocked_now.date()) populate_cycle_obs(500, asof=mocked_now.date()) populate_cycle_prediction(asof=mocked_now.date()) data_provider = DataProviderDjango() execution_provider = ExecutionProviderDjango() idata = build_instruments(data_provider) result = calculate_portfolio(settings=settings, data_provider=data_provider, execution_provider=execution_provider, idata=idata) self.assertTrue(True)
def test_perturbate_mix1(self): GoalMetricFactory.create( group=self.goal_settings.metric_group, feature=self.equity, type=GoalMetric.METRIC_TYPE_PORTFOLIO_MIX, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, rebalance_thr=0.05, configured_val=0.01, comparison=GoalMetric.METRIC_COMPARISON_EXACTLY) GoalMetricFactory.create( group=self.goal_settings.metric_group, feature=self.bond, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, type=GoalMetric.METRIC_TYPE_PORTFOLIO_MIX, rebalance_thr=0.05, configured_val=0.01, comparison=GoalMetric.METRIC_COMPARISON_MAXIMUM) GoalMetricFactory.create( group=self.goal_settings.metric_group, feature=self.equity, type=GoalMetric.METRIC_TYPE_RISK_SCORE, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, rebalance_thr=0.5, configured_val=0.5) opt_inputs = calc_opt_inputs(self.goal.approved_settings, self.idata, self.data_provider, self.execution_provider) weights, min_weights = perturbate_mix(self.goal, opt_inputs) self.assertTrue( min_weights[self.t1.id] + min_weights[self.t2.id] < 0.01 + 0.05) self.assertTrue( min_weights[self.t3.id] + min_weights[self.t4.id] < 0.01 + 0.05)
def test_full_in_execution_path_IB(self): GoalMetricFactory.create( group=self.goal_settings.metric_group, feature=self.equity, type=GoalMetric.METRIC_TYPE_PORTFOLIO_MIX, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, rebalance_thr=0.05, configured_val=0.3, comparison=GoalMetric.METRIC_COMPARISON_MINIMUM) GoalMetricFactory.create( group=self.goal_settings.metric_group, feature=self.bond, type=GoalMetric.METRIC_TYPE_PORTFOLIO_MIX, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, rebalance_thr=0.05, configured_val=0.7, comparison=GoalMetric.METRIC_COMPARISON_MAXIMUM) GoalMetricFactory.create( group=self.goal_settings.metric_group, feature=self.equity, type=GoalMetric.METRIC_TYPE_RISK_SCORE, rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE, rebalance_thr=0.5, configured_val=0.5) goals = Goal.objects.all() process(self.data_provider, self.execution_provider, 5) for goal in goals: sum_volume = Execution.objects.filter(distributions__execution_request__goal=goal) \ .aggregate(sum=Sum('volume')) sum_amount = Execution.objects.filter(distributions__execution_request__goal=goal) \ .aggregate(sum=Sum('volume')) self.assertTrue(sum_volume['sum'] == sum_amount['sum'])
def initialize_backtest(cls, tickers): ticker_list = list() equity_asset_class = AssetClassFactory\ .create(name='US_MUNICIPAL_BONDS', investment_type=InvestmentTypeFactory.create(name='US_MUNICIPAL_BONDS')) for t in tickers: market_index = MarketIndexFactory.create() ticker = TickerFactory.create(symbol=t, asset_class=equity_asset_class, benchmark=market_index) ticker_list.append(ticker) portfolio_set = PortfolioSetFactory.create( name='portfolio_set1', risk_free_rate=0.02, asset_classes=[equity_asset_class], portfolio_provider=get_default_provider()) goal_settings = GoalSettingFactory.create( target=100000, completion=datetime.date(2000, 1, 1), hedge_fx=False, rebalance=True, ) goal_metric = GoalMetricFactory.create( group=goal_settings.metric_group, type=GoalMetric.METRIC_TYPE_RISK_SCORE) PortfolioFactory.create(setting=goal_settings) #GoalMetricGroupFactory.create() return GoalFactory.create(account=Fixture1.personal_account1(), name='goal1', type=Fixture1.goal_type1(), cash_balance=10000, approved_settings=goal_settings, selected_settings=goal_settings, active_settings=goal_settings, portfolio_set=portfolio_set)
def test_calc_opt_inputs_no_assets_for_constraint(self): """ Makes sure when we have no assets filling a constraint, we behave appropriately. """ # This fund has a different feature to the one in the mix metric, but it is in the correct portfolio set. fund1 = TickerFactory.create() AssetFeatureValueFactory.create(assets=[fund1]) ps1 = PortfolioSetFactory.create(asset_classes=[fund1.asset_class]) # Create a settings object with a metric for a feature with no instruments in the current portfolio set. feature = AssetFeatureValueFactory.create() settings = GoalSettingFactory.create() risk_metric = GoalMetricFactory.create(group=settings.metric_group) mix_metric = GoalMetricFactory.create( group=settings.metric_group, type=GoalMetric.METRIC_TYPE_PORTFOLIO_MIX, feature=feature, comparison=GoalMetric.METRIC_COMPARISON_MAXIMUM, configured_val=.3) goal = GoalFactory.create(selected_settings=settings, portfolio_set=ps1) # The below fund has the desired feature, but is not in the goal's portfolio set. fund2 = TickerFactory.create() feature.assets.add(fund2) # Create some instrument data for the two assets self.m_scale = MarkowitzScaleFactory.create() # populate the data needed for the prediction # We need at least 500 days as the cycles go up to 70 days and we need at least 7 cycles. populate_prices(500, asof=mocked_now.date()) populate_cycle_obs(500, asof=mocked_now.date()) populate_cycle_prediction(asof=mocked_now.date()) data_provider = DataProviderDjango() idata = build_instruments(data_provider) execution_provider = ExecutionProviderDjango() # Get the opt inputs, there should be no constraint for the max for the feature with no funds. result = calc_opt_inputs(settings=settings, idata=idata, data_provider=data_provider, execution_provider=execution_provider) xs, lam, constraints, settings_instruments, settings_symbol_ixs, lcovars = result self.assertEqual(len(constraints), 3) # All positive, and sum to 1 # Then create a fund in the portfolio I want. We should get a constraint for the maximum for the feature. fund3 = TickerFactory.create(asset_class=fund1.asset_class) feature.assets.add(fund3) delete_data() populate_prices(500, asof=mocked_now.date()) populate_cycle_obs(500, asof=mocked_now.date()) populate_cycle_prediction(asof=mocked_now.date()) idata = build_instruments(data_provider) result = calc_opt_inputs(settings=settings, idata=idata, data_provider=data_provider, execution_provider=execution_provider) xs, lam, constraints, settings_instruments, settings_symbol_ixs, lcovars = result self.assertEqual(len(constraints), 4) # All positive, sum to 1, and the max constraint