예제 #1
0
 def test_get_asset_weights_held_less_than1y_without_new_postions(self):
     fund = TickerFactory.create(unit_price=2.1)
     goal = GoalFactory.create()
     today = datetime.date(2016, 1, 1)
     # Create a 6 month old execution, transaction and a distribution that caused the transaction
     Fixture1.create_execution_details(goal, fund, 10, 2, datetime.date(2014, 6, 1))
     ep = ExecutionProviderDjango()
     vals = ep.get_asset_weights_held_less_than1y(goal, today)
     self.assertEqual(len(vals), 0)
예제 #2
0
    def test_get_asset_weights_without_tax_winners(self):
        fund = TickerFactory.create(unit_price=3)
        goal = GoalFactory.create()
        today = datetime.date(2016, 1, 1)
        # Create a 6 month old execution, transaction and a distribution that caused the transaction
        Fixture1.create_execution_details(goal, fund, 10, 2, datetime.date(2014, 6, 1))
        Fixture1.create_execution_details(goal, fund, 10, 4, datetime.date(2015, 6, 1))

        ep = ExecutionProviderDjango()
        vals = ep.get_asset_weights_without_tax_winners(goal=goal)
        self.assertAlmostEqual(vals[fund.id], (10*3) / goal.available_balance)
예제 #3
0
    def calculate_portfolio_for_selected(self):
        from portfolios.providers.data.django import DataProviderDjango
        from portfolios.providers.execution.django import ExecutionProviderDjango
        from portfolios.calculation import Unsatisfiable, calculate_portfolio, get_instruments

        data_provider = DataProviderDjango()
        execution_provider = ExecutionProviderDjango()
        idata = get_instruments(data_provider)
        try:
            weights, er, stdev = calculate_portfolio(self.selected_settings,
                                                     data_provider,
                                                     execution_provider, True,
                                                     idata)
            portfolio = Portfolio.objects.create(
                setting=self.selected_settings,
                stdev=stdev,
                er=er,
            )
            items = [
                PortfolioItem(portfolio=portfolio,
                              asset=Ticker.objects.get(id=tid),
                              weight=weight,
                              volatility=idata[0].loc[tid, tid])
                for tid, weight in weights.iteritems()
            ]
            PortfolioItem.objects.bulk_create(items)
        except Unsatisfiable:
            # We detect when loading a goal in the allocation screen if there has been no portfolio created
            # and return a message to the user. It it perfectly reasonable for a goal to be created without a
            # portfolio.
            logger.exception(
                "No suitable portfolio could be found. Leaving empty.")
예제 #4
0
 def handle(self, *args, **options):
     from portfolios.providers.execution.django import ExecutionProviderDjango
     data_provider = DataProviderDjango(timezone.now().date())
     execution_provider = ExecutionProviderDjango()
     idata = get_instruments(data_provider)
     for gs in GoalSetting.objects.all():
         if gs.can_rebalance:
             logger.info('Rebalancing goal %s' % gs.goal)
             rebalance(gs.goal, idata, data_provider, execution_provider)
예제 #5
0
    def __init__(self):
        self._covars = self._samples = self._instruments = self._masks = None
        self.data_provider = DataProviderBacktest(sliding_window_length=250 *
                                                  5,
                                                  dir='/backtesting/')
        self.execution_provider = ExecutionProviderDjango()
        MarkowitzScaleFactory.create()
        self.data_provider.get_goals()

        self.goal = None
예제 #6
0
 def handle_noargs(self, **options):
     '''
     runs process(data_provider, execution_provider, delay) in betasmartz / execution / end_of_day.py 
     '''
     from datetime import datetime
     from execution.end_of_day import process
     from portfolios.providers.execution.django import ExecutionProviderDjango
     from portfolios.providers.data.django import DataProviderDjango
     data_provider = DataProviderDjango(datetime.now().date())
     execution_provider = ExecutionProviderDjango()
     process(data_provider, execution_provider, 5)
예제 #7
0
    def setUp(self):
        self.t1 = TickerFactory.create(symbol='SPY', unit_price=5)
        self.t2 = TickerFactory.create(symbol='VEA', unit_price=5)
        self.t3 = TickerFactory.create(symbol='TIP', unit_price=100)
        self.t4 = TickerFactory.create(symbol='IEV', unit_price=100)

        self.t5 = TickerFactory.create(symbol='IEV2',
                                       unit_price=100,
                                       asset_class=self.t4.asset_class)

        self.equity = AssetFeatureValueFactory.create(
            name='equity', assets=[self.t1, self.t2])
        self.bond = AssetFeatureValueFactory.create(name='bond',
                                                    assets=[self.t3, self.t4])

        self.goal_settings = GoalSettingFactory.create()
        asset_classes = [
            self.t1.asset_class, self.t2.asset_class, self.t3.asset_class,
            self.t4.asset_class
        ]
        portfolio_set = PortfolioSetFactory.create(name='set',
                                                   risk_free_rate=0.01,
                                                   asset_classes=asset_classes)
        self.goal = GoalFactory.create(approved_settings=self.goal_settings,
                                       active_settings=self.goal_settings,
                                       cash_balance=100,
                                       portfolio_set=portfolio_set)

        self.tickers = [self.t1, self.t2, self.t3, self.t4, self.t4]
        self.prices = [4, 4, 90, 90, 95]
        self.quantities = [5, 5, 5, 5, 5]
        self.executed = [
            date(2015, 1, 1),
            date(2016, 1, 1),
            date(2015, 1, 1),
            date(2016, 1, 1),
            date(2016, 1, 1)
        ]

        self.execution_details = []
        for i in range(5):
            execution = Fixture1.create_execution_details(
                self.goal, self.tickers[i], self.quantities[i], self.prices[i],
                self.executed[i])
            self.execution_details.append(execution)

        self.data_provider = DataProviderDjango(mocked_now.date())
        self.execution_provider = ExecutionProviderDjango()
        MarkowitzScaleFactory.create()
        self.setup_performance_history()
        self.idata = get_instruments(self.data_provider)

        self.portfolio = PortfolioFactory.create(setting=self.goal_settings)
        self.current_weights = get_held_weights(self.goal)
예제 #8
0
 def handle(self, *args, **options):
     # calculate portfolios
     data_provider = DataProviderDjango()
     exec_provider = ExecutionProviderDjango()
     for goal in Goal.objects.all():
         if goal.selected_settings is not None:
             try:
                 calculate_portfolios(setting=goal.selected_settings,
                                      data_provider=data_provider,
                                      execution_provider=exec_provider)
             except Unsatisfiable as e:
                 logger.warn(e)
예제 #9
0
파일: views.py 프로젝트: dan0712/django-app
    def calculate_all_portfolios(self, request, pk=None, **kwargs):
        """
        Called to calculate all the portfolio objects for 100 different risk scores for the supplied settings.
        """
        goal = self.get_object()

        check_state(Goal.State(goal.state), Goal.State.ACTIVE)

        setting_str = request.query_params.get('setting', None)
        if not setting_str:
            logger.debug(
                'setting parameter missing from calculate_all_portfolios query'
            )
            raise ValidationError(
                "Query parameter 'setting' must be specified and a valid JSON string"
            )
        try:
            setting = ujson.loads(setting_str)
        except ValueError:
            logger.debug(
                'setting parameter for calculate_all_portfolios query not valid json'
            )
            raise ValidationError(
                "Query parameter 'setting' must be a valid json string")

        # Create the settings from the dict
        serializer = serializers.GoalSettingStatelessSerializer(data=setting)
        serializer.is_valid(raise_exception=True)
        settings = serializer.create_stateless(serializer.validated_data, goal)

        # Calculate the portfolio
        try:
            data_provider = DataProviderDjango()
            execution_provider = ExecutionProviderDjango()
            data = [
                self.build_portfolio_data(item[1], item[0]) for item in
                calculate_portfolios(setting=settings,
                                     data_provider=data_provider,
                                     execution_provider=execution_provider)
            ]
            return Response(data)
        except Unsatisfiable as e:
            rdata = {'reason': "No portfolio could be found: {}".format(e)}

            if e.req_funds is not None:
                rdata['req_funds'] = e.req_funds

            return Response({'error': rdata},
                            status=status.HTTP_400_BAD_REQUEST)
예제 #10
0
def process(modeladmin, request, queryset):
    from datetime import datetime
    from execution.end_of_day import process
    from portfolios.providers.execution.django import ExecutionProviderDjango
    from portfolios.providers.data.django import DataProviderDjango
    data_provider = DataProviderDjango(datetime.now().date())
    execution_provider = ExecutionProviderDjango()
    try:
        process(data_provider, execution_provider, 5, queryset)
        modeladmin.message_user(
            request, "Selected Goals has been processed successfully.")
    except Exception as e:
        modeladmin.message_user(request,
                                "Error! Can't process.",
                                level=messages.ERROR)
예제 #11
0
    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)
예제 #12
0
    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)
예제 #13
0
    def setUp(self):
        self.t1 = TickerFactory.create(symbol='SPY', unit_price=5)
        self.t2 = TickerFactory.create(symbol='VEA', unit_price=5)
        self.t3 = TickerFactory.create(symbol='TIP', unit_price=100)
        self.t4 = TickerFactory.create(symbol='IEV', unit_price=100)

        self.equity = AssetFeatureValueFactory.create(
            name='equity', assets=[self.t1, self.t2])
        self.bond = AssetFeatureValueFactory.create(name='bond',
                                                    assets=[self.t3, self.t4])

        self.goal_settings = GoalSettingFactory.create()
        asset_classes = [
            self.t1.asset_class, self.t2.asset_class, self.t3.asset_class,
            self.t4.asset_class
        ]
        portfolio_set = PortfolioSetFactory.create(name='set',
                                                   risk_free_rate=0.01,
                                                   asset_classes=asset_classes)
        self.goal = GoalFactory.create(approved_settings=self.goal_settings,
                                       cash_balance=100,
                                       portfolio_set=portfolio_set)

        Fixture1.create_execution_details(self.goal, self.t1, 5, 4,
                                          date(2016, 1, 1))
        Fixture1.create_execution_details(self.goal, self.t2, 5, 4,
                                          date(2016, 1, 1))
        Fixture1.create_execution_details(self.goal, self.t3, 5, 90,
                                          date(2016, 1, 1))
        Fixture1.create_execution_details(self.goal, self.t4, 5, 90,
                                          date(2016, 1, 1))
        Fixture1.create_execution_details(self.goal, self.t4, 5, 90,
                                          date(2016, 1, 1))

        self.data_provider = DataProviderDjango()
        self.execution_provider = ExecutionProviderDjango()
        MarkowitzScaleFactory.create()
        self.setup_performance_history()
        self.idata = get_instruments(self.data_provider)
예제 #14
0
    def calculate_portfolio(self, request, pk=None, **kwargs):
        """
        Called to calculate a portfolio object for a set of supplied settings.
        """
        goal = self.get_object()

        check_state(Goal.State(goal.state),
                    [Goal.State.ACTIVE, Goal.State.INACTIVE])

        setting_str = request.query_params.get('setting', None)
        if not setting_str:
            raise ValidationError(
                "Query parameter 'setting' must be specified and a valid JSON string"
            )
        try:
            setting = ujson.loads(setting_str)
        except ValueError:
            raise ValidationError(
                "Query parameter 'setting' must be a valid json string")

        # Create the settings object from the dict
        serializer = serializers.GoalSettingStatelessSerializer(data=setting)
        serializer.is_valid(raise_exception=True)
        settings = serializer.create_stateless(serializer.validated_data, goal)

        try:
            data = self.build_portfolio_data(
                calculate_portfolio(
                    settings=settings,
                    data_provider=DataProviderDjango(),
                    execution_provider=ExecutionProviderDjango()))
            return Response(data)
        except Unsatisfiable as e:
            rdata = {'reason': "No portfolio could be found: {}".format(e)}
            if e.req_funds is not None:
                rdata['req_funds'] = e.req_funds

            return Response({'error': rdata},
                            status=status.HTTP_400_BAD_REQUEST)
예제 #15
0
def create_settings(plan):
    """
    Creates some settings that can be used to create a real retirement goal if desired.
    :param plan: The retirement plan to create settings for.
    :return: A GoalSetting object that has been saved in the database.
             The caller needs to destroy it if it is no longer required
    :raises Unsatisfiable if no suitable portfolio could be found for the plan.
    """
    metric_group = GoalMetricGroup.objects.create(type=GoalMetricGroup.TYPE_CUSTOM)
    settings = GoalSetting.objects.create(
        target=0,
        completion=timezone.now().date(),
        hedge_fx=False,
        metric_group=metric_group,
    )

    risk_metric = GoalMetric.objects.create(group=metric_group,
                                            type=GoalMetric.METRIC_TYPE_RISK_SCORE,
                                            comparison=GoalMetric.METRIC_COMPARISON_EXACTLY,
                                            rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE,
                                            rebalance_thr=0.05,
                                            configured_val=plan.desired_risk)

    # Create a mock goal so we can call calculate_portfolio
    class MockGoal(object):
        portfolio_set = plan.client.advisor.default_portfolio_set
        id = 0
        available_balance = 100000
        current_balance = 100000

        def __str__(self):
            return "Retiresmartz calculation Goal for plan: {}".format(plan)

    # Create a dummy settings object for the calculation.
    # We need to do this because we are using a fake goal, as we don't have a real goal yet.
    settings_data = GoalSettingSerializer(instance=settings).data
    calc_settings = GoalSettingStatelessSerializer.create_stateless(settings_data, MockGoal())

    data_provider = DataProviderDjango()
    idata = get_instruments(data_provider)

    weights, er, stdev = calculate_portfolio(
        settings=calc_settings,
        idata=idata,
        data_provider=data_provider,
        execution_provider=ExecutionProviderDjango()
    )

    portfolio = Portfolio.objects.create(
        setting=settings,
        stdev=stdev,
        er=er,
    )
    items = [PortfolioItem(portfolio=portfolio,
                           asset=Ticker.objects.get(id=tid),
                           weight=weight,
                           volatility=idata[0].loc[tid, tid])
             for tid, weight in weights.items()]
    PortfolioItem.objects.bulk_create(items)

    return settings
    def setUp(self):
        Region.objects.create(name="AU")
        Region.objects.create(name="UK")
        Region.objects.create(name="US")
        AssetClass.objects.create(name="US_BONDS",
                                  investment_type=InvestmentType.Standard.BONDS.get(),
                                  display_order=1)
        AssetClass.objects.create(name="AU_STOCKS",
                                  investment_type=InvestmentType.Standard.STOCKS.get(),
                                  display_order=2)
        AssetClass.objects.create(name="AU_STOCK_MUTUALS",
                                  investment_type=InvestmentType.Standard.STOCKS.get(),
                                  display_order=3)

        index = MarketIndex.objects.create(id=1,
                                           display_name='ASSIndex',
                                           region=Region.objects.get(name="AU"),
                                           currency='AUD',
                                           data_api='bloomberg',
                                           data_api_param='MI1')

        ass = Ticker.objects.create(symbol="ASS",
                                    display_name='AU Stock 1',
                                    ethical=False,
                                    region=Region.objects.get(name="AU"),
                                    asset_class=AssetClass.objects.get(name='AU_STOCKS'),
                                    ordering=1,
                                    description='some stock',
                                    benchmark=index,
                                    data_api='portfolios.api.bloomberg',
                                    data_api_param='ASS')

        ubs = Ticker.objects.create(symbol="USB",
                                    display_name='US Bond 1',
                                    ethical=True,
                                    region=Region.objects.get(name="US"),
                                    asset_class=AssetClass.objects.get(name='US_BONDS'),
                                    ordering=1,
                                    description='some stock',
                                    benchmark=index,
                                    data_api='portfolios.api.bloomberg',
                                    data_api_param='USB')
        usb1 = Ticker.objects.create(symbol="USB1",
                                     display_name='US Bond 2',
                                     ethical=False,
                                     region=Region.objects.get(name="US"),
                                     asset_class=AssetClass.objects.get(name='US_BONDS'),
                                     ordering=1,
                                     description='some stock',
                                     benchmark=index,
                                     data_api='portfolios.api.bloomberg',
                                     data_api_param='USB1')
        aums = Ticker.objects.create(symbol="AUMS",
                                     display_name='AU Mutual Stocks 1',
                                     ethical=True,
                                     region=Region.objects.get(name="AU"),
                                     asset_class=AssetClass.objects.get(name='AU_STOCK_MUTUALS'),
                                     etf=False,
                                     ordering=1,
                                     description='some stock',
                                     benchmark=index,
                                     data_api='portfolios.api.bloomberg',
                                     data_api_param='AUMS')

        self._data_provider = DataProviderDjango()
        self._execution_provider = ExecutionProviderDjango()
        self._covars, self._samples, self._instruments, self._masks = build_instruments(self._data_provider)
        MarkowitzScale.objects.create(date=self._data_provider.get_current_date(),
                                      min=-1,
                                      max=1,
                                      a=1,
                                      b=2,
                                      c=3)
예제 #17
0
    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
예제 #18
0
    def create(self, validated_data):
        """
        Override the default create because we need to generate a portfolio.
        :param validated_data:
        :return: The created Goal
        """
        account = validated_data['account']

        data_provider = DataProviderDjango()
        execution_provider = ExecutionProviderDjango()
        idata = get_instruments(data_provider)

        with transaction.atomic():
            metric_group = GoalMetricGroup.objects.create(
                type=GoalMetricGroup.TYPE_CUSTOM)
            settings = GoalSetting.objects.create(
                target=validated_data['target'],
                completion=validated_data['completion'],
                hedge_fx=False,
                metric_group=metric_group,
            )

            portfolio_provider_id = validated_data[
                'portfolio_provider'] if 'portfolio_provider' in validated_data else get_default_provider_id(
                )

            portfolio_set_id = ''
            portfolio_providers = PortfolioProvider.objects.all()
            portfolio_provider = get_default_provider()
            for pp in portfolio_providers:
                if pp.id == portfolio_provider_id:
                    portfolio_provider = pp

            if portfolio_provider.type == constants.PORTFOLIO_PROVIDER_TYPE_KRANE:
                portfolio_set_type = constants.PORTFOLIO_SET_TYPE_KRANE
            elif portfolio_provider.type == constants.PORTFOLIO_PROVIDER_TYPE_AON:
                portfolio_set_type = constants.PORTFOLIO_SET_TYPE_AON
            elif portfolio_provider.type == constants.PORTFOLIO_PROVIDER_TYPE_LEE:
                portfolio_set_type = constants.PORTFOLIO_SET_TYPE_LEE
            else:
                raise Exception('unhandled portfolio_provider_id')

            portfolio_sets = PortfolioSet.objects.all()
            portfolio_set = account.default_portfolio_set
            for ps in portfolio_sets:
                if ps.type == portfolio_set_type:
                    portfolio_set = ps

            goal = Goal.objects.create(
                account=account,
                name=validated_data['name'],
                type=validated_data['type'],
                portfolio_set=portfolio_set,
                portfolio_provider=portfolio_provider,
                selected_settings=settings,
            )
            # Based on the risk profile, and whether an ethical profile was specified on creation, set up Metrics.
            recommended_risk = recommend_risk(settings)
            GoalMetric.objects.create(
                group=metric_group,
                type=GoalMetric.METRIC_TYPE_RISK_SCORE,
                comparison=GoalMetric.METRIC_COMPARISON_EXACTLY,
                rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE,
                rebalance_thr=0.05,
                configured_val=recommended_risk)
            if validated_data['ethical']:
                GoalMetric.objects.create(
                    group=metric_group,
                    type=GoalMetric.METRIC_TYPE_PORTFOLIO_MIX,
                    feature=AssetFeatureValue.Standard.SRI_OTHER.get_object(),
                    comparison=GoalMetric.METRIC_COMPARISON_EXACTLY,
                    rebalance_type=GoalMetric.REBALANCE_TYPE_ABSOLUTE,
                    rebalance_thr=0.05,
                    configured_val=1  # Start with 100% ethical.
                )

            # Make sure the risk score assigned is appropriate for the goal.
            try:
                validate_risk_score(settings)
            except CVE as verr:
                raise ValidationError(verr.message)

            # Add the initial deposit if specified.
            initial_dep = validated_data.pop('initial_deposit', None)
            if initial_dep is not None:
                Transaction.objects.create(reason=Transaction.REASON_DEPOSIT,
                                           to_goal=goal,
                                           amount=initial_dep)

            # Calculate the optimised portfolio
            try:
                weights, er, stdev = calculate_portfolio(
                    settings, data_provider, execution_provider, True, idata)
                portfolio = Portfolio.objects.create(
                    setting=settings,
                    stdev=stdev,
                    er=er,
                )
                items = [
                    PortfolioItem(portfolio=portfolio,
                                  asset=Ticker.objects.get(id=tid),
                                  weight=weight,
                                  volatility=idata[0].loc[tid, tid])
                    for tid, weight in weights.iteritems()
                ]
                PortfolioItem.objects.bulk_create(items)
            except Unsatisfiable:
                # We detect when loading a goal in the allocation screen if there has been no portfolio created
                # and return a message to the user. It it perfectly reasonable for a goal to be created without a
                # portfolio.
                logger.exception(
                    "No suitable portfolio could be found. Leaving empty.")

        return goal