def test_get_detail(self): goal = Fixture1.goal1() url = '/api/v1/goals/{}'.format(goal.id) goal.approve_selected() self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['id'], Fixture1.goal1().id) # Make sure for the detail endpoint, selected settings is an object, but active and approved are null or integer. self.assertEqual(response.data['active_settings'], None) self.assertEqual(response.data['approved_settings'], response.data['selected_settings']['id'])
def test_put_settings_with_risk_too_high(self): url = '/api/v1/goals/{}/selected-settings'.format(Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) rsm = self.risk_score_metric.copy() rsm['configured_val'] = 0.9 new_settings = { "metric_group": {"metrics": [rsm]}, } self.assertLess(max_risk(Fixture1.goal1().selected_settings), 0.9) response = self.client.put(url, new_settings) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_get_pending_transfers(self): # Populate an executed deposit and make sure no pending transfers are returned tx1 = Fixture1.transaction1() url = '/api/v1/goals/{}/pending-transfers'.format(Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, []) # Populate 2 pending transfers (a deposit and withdrawal) and make sure they are both returned. tx2 = Fixture1.pending_deposit1() tx3 = Fixture1.pending_withdrawal1() response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) data = [ { "id": 3, "time": 946652400, "amount": -3500.0 }, { "id": 2, "time": 946648800, "amount": 4000.0 } ] self.assertEqual(response.data, data)
def test_get_all_activity(self): # First add some transactions, balances and eventlogs, and make sure the ActivityLogs are set. Fixture1.settings_event1() Fixture1.transaction_event1() Fixture1.populate_balance1() # 2 Activity lines # We also need to activate the activity logging for the desired event types. ActivityLogEvent.get(Event.APPROVE_SELECTED_SETTINGS) ActivityLogEvent.get(Event.GOAL_BALANCE_CALCULATED) ActivityLogEvent.get(Event.GOAL_DEPOSIT_EXECUTED) url = '/api/v1/goals/{}/activity'.format(Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 4) # Note the Goal not included in response as it is in request. self.assertEqual(response.data[0], {'time': 946684800, 'type': ActivityLogEvent.get(Event.APPROVE_SELECTED_SETTINGS).activity_log.id}) # Setting change approval self.assertEqual(response.data[1], {'balance': 0.0, 'time': 978220800, 'type': ActivityLogEvent.get(Event.GOAL_BALANCE_CALCULATED).activity_log.id}) # Balance # Deposit. Note inclusion of amount, as we're looking at it from the goal perspective. self.assertEqual(response.data[2], {'amount': 3000.0, 'data': [3000.0], 'time': 978307200, 'type': ActivityLogEvent.get(Event.GOAL_DEPOSIT_EXECUTED).activity_log.id}) self.assertEqual(response.data[3], {'balance': 3000.0, 'time': 978307200, 'type': ActivityLogEvent.get(Event.GOAL_BALANCE_CALCULATED).activity_log.id}) # Balance
def test_performance_history_empty(self): url = '/api/v1/goals/{}/performance-history'.format( Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, [])
def test_change_account_cash(self): goal1 = Fixture1.goal1() account = Fixture1.personal_account1() account.all_goals.return_value = [goal1] #no difference account.cash_balance = 0 ib_account = account.ib_account ib_account_cash[ib_account.ib_account] = 0 difference = reconcile_cash_client_account(account) self.assertNotAlmostEqual(0, difference) self.assertEqual(ib_account.ib_account, IB_ACC_1) #deposit - transferred to account.cash_balance ib_account_cash[ib_account.ib_account] = 1100 reconcile_cash_client_account(account) self.assertNotAlmostEqual(0, account.cash_balance) #withdrawal - from account.cash_balance ib_account_cash[ib_account.ib_account] = 900 reconcile_cash_client_account(account) self.assertAlmostEqual(900, account.cash_balance) #exception - sum of goal cash balances > ib_account_cash goal1.cash_balance = 1000 goal1.save() account.cash_balance = 100 ib_account_cash[ib_account.ib_account] = 900 with self.assertRaises(Exception) as cm: reconcile_cash_client_account(account) self.assertTrue(ib_account.ib_account in cm.exception.args[0])
def test_post_settings_with_memo_false_staff(self): # Test POST with a memo and false staff old_events = Log.objects.count() old_memos = EventMemo.objects.count() url = '/api/v1/goals/{}/selected-settings'.format(Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) new_settings = { "completion": "2016-01-01", # Any metrics set must have a risk score metric. "metric_group": { "metrics": [self.risk_score_metric] }, "hedge_fx": False, "event_memo": "Replaced because the old one smelled.", "event_memo_staff": False, } response = self.client.post(url, new_settings) self.assertEqual(response.status_code, status.HTTP_200_OK) # Make sure an event log was written self.assertEqual(old_events + 1, Log.objects.count()) # Make sure an event memo was written self.assertEqual(old_memos + 1, EventMemo.objects.count()) # Make sure the memo was the text I passed, and staff is false. memo = EventMemo.objects.order_by('-id')[0] self.assertFalse(memo.staff) self.assertEqual(memo.comment, new_settings['event_memo'])
def test_max_risk(self): goal = Fixture1.goal1() settings = Fixture1.settings1() client = goal.account.primary_owner # Add the weights for the risk factors Fixture1.populate_risk_profile_questions() # Also populates all possible answers. Fixture1.populate_risk_profile_responses() # we haven't set a net worth or a target, so worth_score isn't a factor # An all-9s account will have a max_risk of 1 self.assertEqual(max_risk(settings), 1.0) # and if they are low risk behavior, high Ability + Sophistication # the max risk is still 1 client.risk_profile_responses.clear() client.risk_profile_responses.add(Fixture1.risk_profile_answer1c()) client.risk_profile_responses.add(Fixture1.risk_profile_answer2c()) self.assertEqual(max_risk(settings), 1.0) # but if they are risky, new and unskilled, recommend no risk client.risk_profile_responses.clear() client.risk_profile_responses.add(Fixture1.risk_profile_answer1d()) client.risk_profile_responses.add(Fixture1.risk_profile_answer2d()) self.assertAlmostEqual(recommend_risk(settings), 0.1, 1) self.assertAlmostEqual(max_risk(settings), 0.1, 1)
def test_recommend_risk_fully_answered(self): # Fully populate the answers, we should get 0.5 goal = Fixture1.goal1() settings = Fixture1.settings1() Fixture1.populate_risk_profile_questions() # Also populates all possible answers. Fixture1.populate_risk_profile_responses() self.assertEqual(recommend_risk(settings), 1.0)
def test_get_goal_settings_by_id(self): goal = Fixture1.goal1() setting = goal.selected_settings url = '/api/v1/goals/{}/settings/{}'.format(goal.id, setting.id) # unauthenticated response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) # authenticated self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertNotEqual(response.data, []) self.assertEqual(response.data.get('id'), setting.id) # 404 check url = '/api/v1/goals/{}/settings/{}'.format(goal.id, 99999) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) # Unauthorized user check self.client.force_authenticate(user=Fixture1.client2().user) url = '/api/v1/goals/{}/settings/{}'.format(goal.id, setting.id) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_recommend_risk_fully_unanswered(self): # Populate the questions, we should still get 0.5 goal = Fixture1.goal1() settings = Fixture1.settings1() account = settings.goal.account Fixture1.populate_risk_profile_questions() self.assertEqual(recommend_risk(settings), MINIMUM_RISK)
def test_put_settings_recurring_transactions(self): # Test PUT with good transaction data tx1 = RecurringTransactionFactory.create() tx2 = RecurringTransactionFactory.create() url = '/api/v1/goals/{}/selected-settings'.format(Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) serializer = RecurringTransactionCreateSerializer(tx1) serializer2 = RecurringTransactionCreateSerializer(tx2) settings_changes = { 'recurring_transactions': [ serializer.data, serializer2.data, ], } response = self.client.put(url, settings_changes) self.assertEqual(response.status_code, status.HTTP_200_OK) # bad transaction missing enabled field data = serializer.data del data['enabled'] settings_changes = { 'recurring_transactions': [ data, serializer2.data, ], } response = self.client.put(url, settings_changes) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def goal_opening(self, value): with mock.patch.object(timezone, 'now', self.mocked_date(0)): self.goal = Fixture1.goal1() Transaction.objects.create(reason=Transaction.REASON_DEPOSIT, to_goal=self.goal, amount=value, status=Transaction.STATUS_EXECUTED, executed=timezone.now())
def test_reduce_cash(self): goal1 = Fixture1.goal1() goal1.cash_balance = 1000 cash_available = goal1.cash_balance ticker = TickerFactory.create() ticker.latest_tick = 2 volume = 2000 cash_available, volume = reduce_cash(volume, ticker, cash_available) self.assertAlmostEqual(cash_available, 1.03) self.assertTrue(volume == 497)
def test_put_settings_no_memo(self): # Test PUT with no memo old_events = Log.objects.count() old_memos = EventMemo.objects.count() url = '/api/v1/goals/{}/selected-settings'.format(Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) settings_changes = {"target": 1928355} response = self.client.put(url, settings_changes) self.assertEqual(response.status_code, status.HTTP_200_OK) # Make sure an event log was written self.assertEqual(old_events + 1, Log.objects.count()) # Make sure no event memo was written self.assertEqual(old_memos, EventMemo.objects.count())
def test_validate_risk_score_with_unlimited(self): goal = Fixture1.goal1() setting = Fixture1.settings1() risk_metric = setting.metric_group.metrics.get(type=GoalMetric.METRIC_TYPE_RISK_SCORE) q = RiskProfileQuestionFactory.create(group=goal.account.primary_owner.risk_profile_group) a = RiskProfileAnswerFactory.create(b_score=0, a_score=0, s_score=0, question=q) client = goal.account.primary_owner client.risk_profile_responses.add(a) self.assertGreater(risk_metric.configured_val, 0.01) try: validate_risk_score(setting, True) except ValidationError: self.fail("validate_risk_score() should not raise ValidationError when `risk_score_unlimited` is set.")
def test_recommended_risk_scores(self): """ expects the years parameter for the span of risk scores """ url = '/api/v1/goals/{}/risk-score-data'.format(Fixture1.goal1().id) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['max'], MINIMUM_RISK) self.assertEqual(response.data['recommended'], MINIMUM_RISK)
def test_recommend_risk_fully_answered_bad_questions(self): # Fully populate the answers, but no range in the available question responses, we should get 0.5 goal = Fixture1.goal1() settings = Fixture1.settings1() account = settings.goal.account Fixture1.populate_risk_profile_questions() # Also populates all possible answers. Fixture1.populate_risk_profile_responses() Fixture1.risk_profile_question3() # Add a question we don't have an answer for self.assertEqual(recommend_risk(settings), MINIMUM_RISK) # Now answer the question, we shouldn't get MINIMUM_RISK account.primary_owner.risk_profile_responses.add(Fixture1.risk_profile_answer3a()) self.assertNotEqual(recommend_risk(settings), MINIMUM_RISK)
def test_fully_answered_zero_max(self): goal = Fixture1.goal1() setting = Fixture1.settings1() risk_metric = setting.metric_group.metrics.get(type=GoalMetric.METRIC_TYPE_RISK_SCORE) q = RiskProfileQuestionFactory.create(group=goal.account.primary_owner.risk_profile_group) a = RiskProfileAnswerFactory.create(b_score=0, a_score=0, s_score=0, question=q) client = goal.account.primary_owner client.risk_profile_responses.add(a) self.assertGreater(risk_metric.configured_val, 0.01) with self.assertRaises(ValidationError) as ex: validate_risk_score(setting) risk_metric.configured_val = 0 risk_metric.save() self.assertEqual(validate_risk_score(setting), None) # Should now complete OK. self.assertEqual(max_risk(setting), 0.0) self.assertEqual(recommend_risk(setting), 0.0)
def test_event_memo(self): ''' Tests event memos and assigning multiple events to one activity log item. :return: ''' # Add a public settings event with a memo se = Fixture1.settings_event1() EventMemo.objects.create(event=se, comment='A memo for e1', staff=False) # Add a staff settings event with a memo se2 = Fixture1.settings_event2() EventMemo.objects.create(event=se2, comment='A memo for e2', staff=True) # Add a transaction event without a memo Fixture1.transaction_event1() # We also need to activate the activity logging for the desired event types. # We add selected and update to the same une to test that too al = ActivityLog.objects.create(name="Settings Funk", format_str='Settings messed with') ActivityLogEvent.objects.create( id=Event.APPROVE_SELECTED_SETTINGS.value, activity_log=al) ActivityLogEvent.objects.create( id=Event.UPDATE_SELECTED_SETTINGS.value, activity_log=al) ActivityLogEvent.get(Event.GOAL_DEPOSIT_EXECUTED) url = '/api/v1/goals/{}/activity'.format(Fixture1.goal1().id) # Log in as a client and make sure I see the public settings event, and the transaction, not the staff entry. self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 3) self.assertEqual(response.data[2]['memos'], ['A memo for e1']) self.assertFalse('memos' in response.data[0]) self.assertFalse('memos' in response.data[1]) # Log in as the advisor and make sure I see all three events. self.client.force_authenticate(user=Fixture1.advisor1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 3) self.assertEqual(response.data[2]['memos'], ['A memo for e1']) self.assertEqual(response.data[1]['memos'], ['A memo for e2']) self.assertFalse('memos' in response.data[0])
def test_put_settings_with_memo_no_staff(self): # Test with a memo but no staff old_events = Log.objects.count() old_memos = EventMemo.objects.count() url = '/api/v1/goals/{}/selected-settings'.format(Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) settings_changes = { "target": 1928355, "event_memo": "Changed the target because I took an arrow to the knee." } response = self.client.put(url, settings_changes) self.assertEqual(response.status_code, status.HTTP_200_OK) # Make sure an event log was written self.assertEqual(old_events + 1, Log.objects.count()) # Make sure an event memo was written self.assertEqual(old_memos + 1, EventMemo.objects.count()) # Make sure the memo was the text I passed, and the default for staff is false. memo = EventMemo.objects.order_by('-id')[0] self.assertFalse(memo.staff) self.assertEqual(memo.comment, settings_changes['event_memo'])
def test_recommend_risk(self): goal = Fixture1.goal1() settings = Fixture1.settings1() client = goal.account.primary_owner # Add the weights for the risk factors Fixture1.populate_risk_profile_questions() # Also populates all possible answers. Fixture1.populate_risk_profile_responses() # First lets start with the test_client, who scored 9 for all B,A,S # A goal of 80% of the value on a all-9s account is a bad idea # It's the lowest possible score settings.goal.account.primary_owner.net_worth = 100 settings.goal.cash_balance = 80 self.assertAlmostEqual(recommend_risk(settings), 0.10, 2) # A goal of 50% of the value is just as bad settings.goal.account.primary_owner.net_worth = 100 settings.goal.cash_balance = 50 self.assertAlmostEqual(recommend_risk(settings), 0.10, 2) # A goal of 10% of the value on a all-9s account is 1.0 # meaning this is the safest possible bet settings.goal.account.primary_owner.net_worth = 100 settings.goal.cash_balance = 10 self.assertAlmostEqual(recommend_risk(settings), 1.0, 2) # A goal of 33% of the value on a all-9s account is about 0.5 # Even if you are risky, sophisticated and rich, 30% is a lot settings.goal.account.primary_owner.net_worth = 100 settings.goal.cash_balance = 33 self.assertAlmostEqual(recommend_risk(settings), 0.5, 1) # For a new investor, the best possible suggestion is 10% or less settings.goal.account.primary_owner.net_worth = 100 settings.goal.cash_balance = 10 client.risk_profile_responses.clear() client.risk_profile_responses.add(Fixture1.risk_profile_answer1b()) client.risk_profile_responses.add(Fixture1.risk_profile_answer2b()) self.assertAlmostEqual(recommend_risk(settings), 0.2, 1)
def test_calculate_portfolio(self): goal1 = Fixture1.goal1() goal1.portfolio_set.asset_classes = [ AssetClass.objects.get(name="US_BONDS"), AssetClass.objects.get(name="AU_STOCKS"), AssetClass.objects.get(name="AU_STOCK_MUTUALS") ] goal1.selected_settings.metric_group.metrics = [GoalMetric.objects.create(group=Fixture1.metric_group1(), type=GoalMetric.METRIC_TYPE_RISK_SCORE, rebalance_type="1", configured_val=0.0, comparison=2, rebalance_thr=0.05) ] goal1.selected_settings.SYSTEM_CURRENCY = 'USD' goal1.cash_balance = 1000 idata = get_instruments(self._data_provider) portfolio, er, var = calculate_portfolio(settings=goal1.selected_settings, data_provider=self._data_provider, execution_provider=self._execution_provider, idata=idata) self.assertEqual(len(portfolio), 4)
def test_calculate_portfolios(self): goal1 = Fixture1.goal1() goal1.portfolio_set.asset_classes = [ AssetClass.objects.get(name="US_BONDS"), AssetClass.objects.get(name="AU_STOCKS"), AssetClass.objects.get(name="AU_STOCK_MUTUALS") ] goal1.selected_settings.metric_group.metrics = [GoalMetric.objects.create(group=Fixture1.metric_group1(), type=GoalMetric.METRIC_TYPE_RISK_SCORE, rebalance_type="1", configured_val=0.0, comparison=2, rebalance_thr=0.05) ] goal1.selected_settings.SYSTEM_CURRENCY = 'USD' goal1.cash_balance = 1000 portfolio = Portfolio.objects.create(id=1, er=1, stdev=2, setting=goal1.selected_settings) PortfolioItem.objects.create(asset=Ticker.objects.get(symbol='ASS'), portfolio=portfolio, weight=0.1, volatility=0.2) portfolios = calculate_portfolios(goal1.selected_settings, data_provider=self._data_provider, execution_provider=self._execution_provider) self.assertEqual(len(portfolios), 101)
def test_recommend_risk_no_questions(self): goal = Fixture1.goal1() settings = Fixture1.settings1() account = settings.goal.account self.assertEqual(recommend_risk(settings), MINIMUM_RISK)
def setUp(self): self.bonds_type = InvestmentType.Standard.BONDS.get() self.stocks_type = InvestmentType.Standard.STOCKS.get() self.con = Mock(BaseBroker) self.con.connect.return_value = True #self.con.requesting_market_depth.return_value = False self.market_data = dict() self.market_data['GOOG'] = MarketDepth() single_level = SingleLevelMarketDepth() single_level.bid = 1 single_level.ask = 2 single_level.bid_volume = 50 single_level.ask_volume = 100 self.market_data['GOOG'].add_level(0, single_level) Fixture1.personal_account1() Fixture1.personal_account2() request1 = MarketOrderRequest.objects.create( state=MarketOrderRequest.State.APPROVED.value, account=Fixture1.personal_account1()) request2 = MarketOrderRequest.objects.create( state=MarketOrderRequest.State.APPROVED.value, account=Fixture1.personal_account2()) Fixture1.ib_account1() Fixture1.ib_account2() params = { 'reason': ExecutionRequest.Reason.DRIFT.value, 'goal': Fixture1.goal1(), 'asset': Fixture1.fund3(), 'volume': 5, 'order': request1 } ExecutionRequest.objects.get_or_create(id=1, defaults=params) params = { 'reason': ExecutionRequest.Reason.DRIFT.value, 'goal': Fixture1.goal1(), 'asset': Fixture1.fund4(), 'volume': 5, 'order': request1 } ExecutionRequest.objects.get_or_create(id=2, defaults=params) #Client2 params = { 'reason': ExecutionRequest.Reason.DRIFT.value, 'goal': Fixture1.goal2(), 'asset': Fixture1.fund3(), 'volume': 10, 'order': request2 } ExecutionRequest.objects.get_or_create(id=3, defaults=params) params = { 'reason': ExecutionRequest.Reason.DRIFT.value, 'goal': Fixture1.goal2(), 'asset': Fixture1.fund4(), 'volume': 10, 'order': request2 } ExecutionRequest.objects.get_or_create(id=4, defaults=params)
def test_zero_balance(self): goal = Fixture1.goal1() self.load_fixture('main/tests/fixtures/transactions.json') with mock.patch('main.finance.now', self.mocked_date(0)): total_return = goal.total_return self.assertEqual(total_return, -1.0)
def test_recommend_risk_no_weights(self): goal = Fixture1.goal1() settings = Fixture1.settings1() self.assertEqual(recommend_risk(settings), MINIMUM_RISK)
def test_get_no_activity(self): url = '/api/v1/goals/{}/activity'.format(Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, [])
def test_performance_history(self): goal = GoalFactory.create() prices = ( (Fixture1.fund1(), '20160101', 10), (Fixture1.fund1(), '20160102', 10.5), (Fixture1.fund1(), '20160103', 10.6), (Fixture1.fund1(), '20160104', 10.3), (Fixture1.fund1(), '20160105', 10.1), (Fixture1.fund1(), '20160106', 9.9), (Fixture1.fund1(), '20160107', 10.5), (Fixture1.fund2(), '20160101', 50), (Fixture1.fund2(), '20160102', 51), (Fixture1.fund2(), '20160103', 53), (Fixture1.fund2(), '20160104', 53.5), (Fixture1.fund2(), '20160105', 51), (Fixture1.fund2(), '20160106', 52), (Fixture1.fund2(), '20160107', 51.5), ) Fixture1.set_prices(prices) order_details = ( (Fixture1.personal_account1(), MarketOrderRequest.State.COMPLETE), (Fixture1.personal_account1(), MarketOrderRequest.State.COMPLETE), (Fixture1.personal_account1(), MarketOrderRequest.State.COMPLETE), (Fixture1.personal_account1(), MarketOrderRequest.State.COMPLETE), (Fixture1.personal_account1(), MarketOrderRequest.State.COMPLETE), (Fixture1.personal_account1(), MarketOrderRequest.State.COMPLETE), ) orders = Fixture1.add_orders(order_details) execution_details = ( (Fixture1.fund1(), orders[0], 3, 10.51, -75, '20160102'), (Fixture1.fund1(), orders[0], 4, 10.515, -75.05, '20160102'), (Fixture1.fund1(), orders[1], -1, 10.29, 10, '20160104'), (Fixture1.fund2(), orders[2], 2, 53.49, -110, '20160104'), (Fixture1.fund2(), orders[2], 8, 53.5, -430, '20160104'), (Fixture1.fund1(), orders[3], -3, 10.05, 30, '20160105'), (Fixture1.fund2(), orders[4], -3, 50.05, 145, '20160105'), (Fixture1.fund2(), orders[4], -2, 50.04, 98, '20160105'), (Fixture1.fund2(), orders[5], -5, 52, 255, '20160106'), ) executions = Fixture1.add_executions(execution_details) execution_requests = Fixture1.add_execution_requests( goal, execution_details, executions) # We distribute the entire executions to one goal. distributions = ( (executions[0], 3, Fixture1.goal1()), (executions[1], 4, Fixture1.goal1()), (executions[2], -1, Fixture1.goal1()), (executions[3], 2, Fixture1.goal1()), (executions[4], 8, Fixture1.goal1()), (executions[5], -3, Fixture1.goal1()), (executions[6], -3, Fixture1.goal1()), (executions[7], -2, Fixture1.goal1()), (executions[8], -5, Fixture1.goal1()), ) Fixture1.add_execution_distributions(distributions, execution_requests) url = '/api/v1/goals/{}/performance-history'.format( Fixture1.goal1().id) self.client.force_authenticate(user=Fixture1.client1().user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data[0], (16802, 0)) # 20160102 self.assertEqual(response.data[1], (16803, Decimal('0.009524'))) self.assertEqual(response.data[2], (16804, Decimal('-0.028302'))) self.assertEqual(response.data[3], (16805, Decimal('-0.043901'))) self.assertEqual(response.data[4], (16806, Decimal('-0.019802'))) self.assertEqual(response.data[5], (16807, Decimal('0.060606'))) self.assertEqual(response.data[6], (16808, 0))