Beispiel #1
0
    def selected_settings(self, request, pk=None, **kwargs):
        goal = self.get_object()

        if request.method == 'GET':
            serializer = serializers.GoalSettingSerializer(
                goal.selected_settings)
            return Response(serializer.data)

        with transaction.atomic():  # So both the log and change get committed.
            sr_id = SupportRequest.get_current(request)
            if request.method == 'POST':
                check_state(Goal.State(goal.state), Goal.State.ACTIVE)
                serializer = serializers.GoalSettingWritableSerializer(
                    data=request.data)
                serializer.is_valid(raise_exception=True)
                event = Event.SET_SELECTED_SETTINGS.log(
                    '{} {}'.format(self.request.method, self.request.path),
                    request.data,
                    user=request.user,
                    obj=goal,
                    support_request_id=sr_id)
                # Write any event memo for the event. All the details are wrapped by the serializer.
                serializer.write_memo(event)
                settings = serializer.save(goal=goal)
                # We use the read-only serializer to send the settings object, not the update serializer.
                serializer = serializers.GoalSettingSerializer(settings)
                headers = self.get_success_headers(serializer.data)
                return Response(serializer.data,
                                status=status.HTTP_200_OK,
                                headers=headers)

            elif request.method == 'PUT':
                check_state(Goal.State(goal.state), Goal.State.ACTIVE)
                settings = goal.selected_settings
                event = Event.UPDATE_SELECTED_SETTINGS.log(
                    '{} {}'.format(self.request.method, self.request.path),
                    request.data,
                    user=request.user,
                    obj=goal,
                    support_request_id=sr_id)
                serializer = serializers.GoalSettingWritableSerializer(
                    settings, data=request.data, partial=True)
                serializer.is_valid(raise_exception=True)
                # Write any event memo for the event. All the details are wrapped by the serializer.
                serializer.write_memo(event)
                settings = serializer.save(goal=goal)
                # We use the read-only serializer to send the settings object, not the update serializer.
                serializer = serializers.GoalSettingSerializer(settings)
                headers = self.get_success_headers(serializer.data)
                return Response(serializer.data,
                                status=status.HTTP_200_OK,
                                headers=headers)
Beispiel #2
0
    def get_context_data(self, *args, **kwargs):
        goal_pk = kwargs.get("goal_pk", None)
        ctx = super(PortfolioAssetClasses, self).get_context_data(*args, **kwargs)

        if goal_pk:
            goal = get_object_or_404(Goal, pk=goal_pk)
            ctx["portfolio_set"] = goal.portfolio_set
        else:
            ctx["portfolio_set"] = Goal().portfolio_set

        return ctx
Beispiel #3
0
 def archive(self, request, pk=None, **kwargs):
     """
     Override this method as we don't want to actually delete the goal,
     just disable it.
     :param instance: The goal to disable
     :return: None
     """
     goal = self.get_object()
     # If I'm an advisor or the goal is unsupervised,
     # archive the goal immediately.
     sr = SupportRequest.get_current(request, as_obj=True)
     # check helped user instead if support request is active
     user, sr_id = (sr.user, sr.id) if sr else (request.user, None)
     if not goal.account.supervised or user.is_advisor:
         check_state(Goal.State(goal.state),
                     [Goal.State.ACTIVE, Goal.State.ARCHIVE_REQUESTED])
         Event.ARCHIVE_GOAL.log('{} {}'.format(request.method,
                                               request.path),
                                user=request.user,
                                obj=goal,
                                support_request_id=sr_id)
         # Set the state to archive requested,
         # as the call to archive() requires it.
         goal.state = Goal.State.ARCHIVE_REQUESTED.value
         goal.archive()
     else:
         # I'm a client with a supervised goal, just change the status to
         # ARCHIVE_REQUESTED, and add a notification
         check_state(Goal.State(goal.state), Goal.State.ACTIVE)
         Event.ARCHIVE_GOAL_REQUESTED.log('{} {}'.format(
             request.method, request.path),
                                          user=request.user,
                                          obj=goal,
                                          support_request_id=sr_id)
         # Flag the goal as archive requested.
         goal.state = Goal.State.ARCHIVE_REQUESTED.value
         # TODO: Add a notification to the advisor that the goal is archive requested.
         goal.save()
     return Response(serializers.GoalSerializer(goal).data)
Beispiel #4
0
    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)
Beispiel #5
0
    def get(self, request, *args, **kwargs):
        portfolio_set = Goal().portfolio_set
        goal_pk = kwargs.get("goal_pk", None)
        if goal_pk:
            try:
                goal = Goal.objects.get(pk=goal_pk,
                                        account__primary_owner=self.client)
            except ObjectDoesNotExist:
                goal = None

            if goal:
                if goal.is_custom_size:
                    if goal.portfolios in [None, "{}", "[]", ""]:
                        try:
                            portfolios = calculate_portfolios(goal)
                            goal.portfolios = ujson.dumps(portfolios, double_precision=2)
                            goal.save()
                        except OptimizationException:
                            goal.custom_regions = None
                            goal.save()
                            portfolios = ujson.loads(goal.portfolio_set.portfolios)
                    else:
                        portfolios = ujson.loads(goal.portfolios)
                else:
                    portfolios = ujson.loads(goal.portfolio_set.portfolios)

                ret = []
                for k in portfolios:
                    new_pr = {
                        "risk": int(100 * portfolios[k]["risk"]) / 100,
                        "expectedReturn": portfolios[k]["expectedReturn"],
                        "volatility": portfolios[k]["volatility"],
                        'allocations': portfolios[k]["allocations"]
                    }
                    ret.append(new_pr)
                return HttpResponse(ujson.dumps(ret), content_type="application/json")

        ret = []
        portfolios = ujson.loads(portfolio_set.portfolios)
        for k in portfolios:
            new_pr = {
                "risk": int(100 * portfolios[k]["risk"]) / 100,
                "expectedReturn": portfolios[k]["expectedReturn"],
                "volatility": portfolios[k]["volatility"],
                'allocations': portfolios[k]["allocations"]
            }
            ret.append(new_pr)

        return HttpResponse(ujson.dumps(ret), content_type="application/json")
Beispiel #6
0
    def deposit(self, request, pk=None, **kwargs):
        goal = self.get_object()

        check_state(Goal.State(goal.state), Goal.State.ACTIVE)
        sr_id = SupportRequest.get_current(request)
        Event.GOAL_DEPOSIT.log('{} {}'.format(request.method, request.path),
                               request.data,
                               user=request.user,
                               obj=goal,
                               support_request_id=sr_id)
        serializer = serializers.TransactionCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(to_goal=goal, reason=Transaction.REASON_DEPOSIT)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=headers)
Beispiel #7
0
    def revert_selected(self, request, pk=None, **kwargs):
        """
        Called to revert the current selected-settings to the approved-settings
        Returns a validation error if there is no approved-settings.
        """
        goal = self.get_object()
        check_state(Goal.State(goal.state), Goal.State.ACTIVE)
        if not goal.approved_settings:
            raise ValidationError("No settings have yet been approved for "
                                  "this Goal, cannot revert to last approved.")
        sr_id = SupportRequest.get_current(request)
        Event.REVERT_SELECTED_SETTINGS.log('{} {}'.format(
            request.method, request.path),
                                           user=request.user,
                                           obj=goal,
                                           support_request_id=sr_id)
        goal.revert_selected()
        serializer = serializers.GoalSettingSerializer(goal.selected_settings)

        return Response(serializer.data)
def calculate_portfolios():
    # calculate default portfolio
    yahoo_api = get_api("YAHOO")

    for ps in PortfolioSet.objects.all():
        goal = Goal()
        goal.custom_portfolio_set = ps
        ps.portfolios = json.dumps(
            calculate_portfolios_for_goal(goal, api=yahoo_api))
        ps.save()

    # calculate portfolios
    for goal in Goal.objects.all():
        if goal.is_custom_size:
            goal.portfolios = json.dumps(
                calculate_portfolios_for_goal(goal, api=yahoo_api))
            goal.save()
Beispiel #9
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)

        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)
Beispiel #10
0
    def approve_selected(self, request, pk=None, **kwargs):
        """
        Called to make the currently selected settings approved by the advisor,
        ready to be activated next time the account is processed (rebalance).
        """
        sr = SupportRequest.get_current(request, as_obj=True)
        # check helped user instead if support request is active
        user, sr_id = (sr.user, sr.id) if sr else (request.user, None)
        if not user.is_advisor:
            raise PermissionDenied('Only an advisor can approve selections.')

        goal = self.get_object()
        check_state(Goal.State(goal.state), Goal.State.ACTIVE)
        Event.APPROVE_SELECTED_SETTINGS.log('{} {}'.format(
            request.method, request.path),
                                            user=request.user,
                                            obj=goal,
                                            support_request_id=sr_id)
        goal.approve_selected()

        serializer = serializers.GoalSettingSerializer(goal.approved_settings)

        return Response(serializer.data)
Beispiel #11
0
    def withdraw(self, request, pk=None, **kwargs):
        goal = self.get_object()

        check_state(Goal.State(goal.state), Goal.State.ACTIVE)
        sr_id = SupportRequest.get_current(request)
        Event.GOAL_WITHDRAWAL.log('{} {}'.format(request.method, request.path),
                                  request.data,
                                  user=request.user,
                                  obj=goal,
                                  support_request_id=sr_id)
        serializer = serializers.TransactionCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # Make sure the total amount for the goal is larger than the pending withdrawal amount.
        if goal.current_balance + 0.0000001 < serializer.validated_data[
                'amount']:
            emsg = "Goal's current balance: {} is less than the desired withdrawal amount: {}"
            raise SystemConstraintError(
                emsg.format(goal.current_balance,
                            serializer.validated_data['amount']))
        serializer.save(from_goal=goal, reason=Transaction.REASON_WITHDRAWAL)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=headers)
Beispiel #12
0
    def post(self, requests, *args, **kwargs):

        if "HTTP_X_HTTP_METHOD_OVERRIDE" in requests.META:
            if requests.META["HTTP_X_HTTP_METHOD_OVERRIDE"] == "DELETE":
                return self.delete(requests, *args, **kwargs)

        model = ujson.loads(requests.POST.get("model", '{}'))
        goal = Goal()
        goal.account = self.client.accounts.first()
        goal.name = model.get("name")
        goal.type = model.get("goalType")

        if "ETHICAL" in goal.type:
            goal.custom_portfolio_set = PortfolioSet.objects.get(name="Ethical")

        goal.account_type = model.get("accountType")
        goal.completion_date = datetime.strptime(
            model.get("goalCompletionDate"), '%Y%m%d%H%M%S')
        goal.allocation = model.get("allocation")
        goal.target = model.get("goalAmount", None)
        if goal.target is None:
            goal.target = 0
        goal.income = model.get("income", False)
        goal.save()
        return HttpResponse(ujson.dumps({"id": goal.pk}), content_type='application/json')