def test_invalid_object_missing_properties(self):
        portfolio_dict = {
            "creation_date":
            "2020-04-14T12:20:50.219487+00:00",
            "price_date":
            "2020-03-31T04:00:00+00:00",
            "current_portfolio": [{
                "ticker_symbol": "AAPL",
                "quantity": 1000,
                "purchase_date": "2020-03-31T04:00:00+00:00",
                "purchase_price": 123.45,
                "current_price": 234.56,
                "current_returns": 0.9,
                "trade_state": "FILLED",
                "order_id": None
            }],
            "securities_set": [{
                "ticker_symbol": "AAPL",
                "analysis_price": 100,
                "current_price": 102,
                "current_returns": 0.02
            }]
        }

        with self.assertRaises(ValidationError):
            Portfolio.from_dict(portfolio_dict)
    def test_valid_object_no_portfolio(self):
        portfolio_dict = {
            "portfolio_id":
            "xxx",
            "set_id":
            "yyy",
            "creation_date":
            "2020-04-14T12:20:50.219487+00:00",
            "price_date":
            "2020-03-31T04:00:00+00:00",
            "current_portfolio": {
                "securities": [{
                    "ticker_symbol": "AAPL",
                    "quantity": 1000,
                    "purchase_date": "2020-03-31T04:00:00+00:00",
                    "purchase_price": 123.45,
                    "current_price": 234.56,
                    "current_returns": 0.9,
                    "trade_state": "FILLED",
                    "order_id": None
                }]
            },
            "securities_set": [{
                "ticker_symbol": "AAPL",
                "analysis_price": 100,
                "current_price": 102,
                "current_returns": 0.02
            }]
        }

        Portfolio.from_dict(portfolio_dict)
    def test_update_portfolio_too_small(self):
        security_recommendation = SecurityRecommendationSet.from_dict(
            self.sr_dict)
        portfolio = Portfolio()
        portfolio.create_empty_portfolio(security_recommendation)

        with self.assertRaises(ValidationError):
            portfolio_mgr_svc.update_portfolio(
                portfolio, security_recommendation, 0)
    def test_create_empty_portfolio_valid(self):
        with patch.object(intrinio_data,
                          'get_latest_close_price',
                          return_value=('2019-08-31', 123.45)):

            recommendation_set = SecurityRecommendationSet.from_dict(
                self.sr_dict)

            portfolio = Portfolio()
            portfolio.create_empty_portfolio(recommendation_set)
    def test_create_empty_portfolio_no_prices(self):
        with patch.object(intrinio_data,
                          'get_latest_close_price',
                          side_effect=DataError("test exception", None)):

            recommendation_set = SecurityRecommendationSet.from_dict(
                self.sr_dict)

            with self.assertRaises(DataError):
                portfolio = Portfolio()
                portfolio.create_empty_portfolio(recommendation_set)
    def test_create_empty_portfolio_invalid_intrinio_response(self):
        with patch.object(intrinio_data,
                          'get_latest_close_price',
                          return_value=('aaaa', 123.45)):

            recommendation_set = SecurityRecommendationSet.from_dict(
                self.sr_dict)

            with self.assertRaises(ValidationError):
                portfolio = Portfolio()
                portfolio.create_empty_portfolio(recommendation_set)
def get_service_inputs(app_ns: str):
    '''
        Returns the required inputs for the recommendation service given
        the application namespace used to identify the appropriate cloud resources.

        Returns
        ----------
        A tuple containing the latest SecurityRecommendationSet
        and Portfolio objects. If a portfolio does not exist, it will
        create a new one.
    '''

    log.info("Loading latest recommendations")
    recommendation_set = SecurityRecommendationSet.from_s3(app_ns)

    if not recommendation_set.is_current(datetime.now()):
        raise ValidationError("Current recommendation set is not valid", None)

    try:
        log.info("Loading current portfolio")
        pfolio = Portfolio.from_s3(app_ns)
    except AWSError as e:
        if e.resource_not_found():
            pfolio = None
        else:
            raise e

    return (pfolio, recommendation_set)
예제 #8
0
def get_service_inputs(app_ns: str):
    '''
        Returns the required inputs for the recommendation service given
        the application namespace used to identify the appropriate cloud resources.

        Returns
        ----------
        A tuple containing the latest SecurityRecommendationSet
        and Portfolio objects. If a portfolio does not exist, it will
        create a new one.
    '''

    log.info("Loading latest recommendations")
    recommendation_set = SecurityRecommendationSet.from_s3(
        app_ns, constants.S3_PRICE_DISPERSION_RECOMMENDATION_SET_OBJECT_NAME)

    business_date = util.get_business_date(
        constants.BUSINESS_DATE_DAYS_LOOKBACK,
        constants.BUSINESS_DATE_CUTOVER_TIME)

    if not recommendation_set.is_current(business_date):
        raise ValidationError("Current recommendation set is not valid", None)

    try:
        log.info("Loading current portfolio")
        pfolio = Portfolio.from_s3(app_ns, constants.S3_PORTFOLIO_OBJECT_NAME)
    except AWSError as e:
        if e.resource_not_found():
            pfolio = None
        else:
            raise e

    return (pfolio, recommendation_set)
예제 #9
0
    def test_synchronize_portfolio_all_extra_portfolio_positions(self):
        portfolio = Portfolio.from_dict(self.base_portfolio)

        broker = Broker()
        broker.synchronize_portfolio(self.base_positions, portfolio)

        portfolio.model['current_portfolio']['securities'].append({
            "ticker_symbol":
            "XXX",
            "quantity":
            1,
            "purchase_date":
            None,
            "purchase_price":
            1.0,
            "current_price":
            1.0,
            "current_returns":
            0.0,
            "trade_state":
            "UNFILLED",
            "order_id":
            None
        })

        self.assertEqual(
            portfolio.get_position('XXX')['trade_state'], 'UNFILLED')
예제 #10
0
    def test_trade_buy_multiple_securities_with_exception(self):

        buy_positions = [('BA', 1.0), ('GE', 1.0), ('XOM', 1.0)]

        # portfolio has 3 positions
        portfolio = deepcopy(self.base_portfolio)

        portfolio = Portfolio.from_dict(portfolio)

        with patch.object(td_ameritrade, 'place_order', side_effect=[
                'order-1', 'order-2', TradeError("Some Error", None, None)]), \
                patch.object(td_ameritrade, 'list_recent_orders', return_value={
                    "order-1": {
                        "status": "FILLED",
                        "symbol": "BA",
                        "quantity": 1,
                        "closeTime": "2020-05-04T03:21:04+0000",
                        "tag": "AA_myuser"
                    },
                    "order-2": {
                        "status": "FILLED",
                        "symbol": "GE",
                        "quantity": 1,
                        "closeTime": "2020-05-04T03:21:04+0000",
                        "tag": "AA_myuser"
                    }
                }):

            broker = Broker()
            self.assertFalse(broker.trade('BUY', buy_positions, portfolio))
예제 #11
0
파일: utils.py 프로젝트: shinezai/trade
def init_portfolio(env):
    accounts = {}
    config = env.config
    start_date = config.base.start_date
    total_cash = 0
    for account_type in config.base.account_list:
        if account_type == ACCOUNT_TYPE.STOCK.value:
            stock_starting_cash = config.base.stock_starting_cash
            if stock_starting_cash == 0:
                raise RuntimeError(
                    _(u"stock starting cash can not be 0, using `--stock-starting-cash 100000`"
                      ))
            accounts[ACCOUNT_TYPE.STOCK] = StockAccount(
                stock_starting_cash, Positions(StockPosition))
            total_cash += stock_starting_cash
        elif account_type == ACCOUNT_TYPE.FUTURE:
            future_starting_cash = config.base.future_starting_cash
            if future_starting_cash == 0:
                raise RuntimeError(
                    _(u"future starting cash can not be 0, using `--future-starting-cash 100000`"
                      ))
            accounts[ACCOUNT_TYPE.FUTURE] = FutureAccount(
                future_starting_cash, Positions(FuturePosition))
            total_cash += future_starting_cash
        else:
            raise NotImplementedError
    return Portfolio(start_date, 1, total_cash, accounts)
예제 #12
0
    def test_trade_buy_single_security(self):

        buy_positions = [('BA', 1.0)]

        portfolio = deepcopy(self.base_portfolio)
        del portfolio['current_portfolio']['securities'][2]
        del portfolio['current_portfolio']['securities'][1]

        portfolio = Portfolio.from_dict(portfolio)

        with patch.object(td_ameritrade, 'place_order', return_value='order-xxx'), \
                patch.object(td_ameritrade, 'list_recent_orders', return_value={
                    "order-xxx": {
                        "status": "FILLED",
                        "symbol": "BA",
                        "quantity": 1,
                        "closeTime": "2020-05-04T03:21:04+0000",
                        "tag": "AA_myuser"
                    },
                }):

            broker = Broker()
            self.assertTrue(broker.trade('BUY', buy_positions, portfolio))

            pos = portfolio.get_position('BA')
            self.assertEqual(pos['trade_state'], 'FILLED')
            self.assertEqual(pos['quantity'], 1)
            self.assertIsNotNone(pos['purchase_date'])
    def test_get_position(self):
        portfolio_dict = {
            "portfolio_id":
            "xxx",
            "set_id":
            "yyy",
            "creation_date":
            "2020-04-14T12:20:50.219487+00:00",
            "price_date":
            "2020-03-31T04:00:00+00:00",
            "current_portfolio": {
                "securities": [{
                    "ticker_symbol": "INTC",
                    "quantity": 100,
                    "purchase_date": None,
                    "purchase_price": 100,
                    "current_price": 100,
                    "current_returns": 0,
                    "trade_state": "UNFILLED",
                    "order_id": None
                }]
            },
            "securities_set": [{
                "ticker_symbol": "AAPL",
                "analysis_price": 100,
                "current_price": 100,
                "current_returns": 0
            }]
        }

        portfolio = Portfolio.from_dict(portfolio_dict)

        self.assertIsNotNone(portfolio.get_position("INTC"))
        self.assertIsNone(portfolio.get_position("XXX"))
    def test_publish_current_returns(self):

        security_recommendation = SecurityRecommendationSet.from_dict(
            self.sr_dict)
        portfolio = Portfolio()
        portfolio.create_empty_portfolio(security_recommendation)
        (new_p, updated) = portfolio_mgr_svc.update_portfolio(
            portfolio, security_recommendation, 1)

        with patch.object(aws_service_wrapper, 'sns_publish_notification',
                          side_effect=AWSError("", None)), \
            patch.object(aws_service_wrapper, 'cf_read_export_value',
                         return_value="some_value"):

            with self.assertRaises(AWSError):
                portfolio_mgr_svc.publish_current_returns(new_p, updated, 'sa')
예제 #15
0
    def test_generate_test_instructions_nothing_to_do(self):
        portfolio = Portfolio.from_dict(self.base_portfolio)
        broker = Broker()
        (sell_list, buy_list) = broker._generate_trade_instructions(
            self.base_positions, portfolio)

        self.assertListEqual(sell_list, [])
        self.assertListEqual(buy_list, [])
    def test_update_portfolio_too_big(self):
        security_recommendation = SecurityRecommendationSet.from_dict(
            self.sr_dict)
        portfolio = Portfolio()
        portfolio.create_empty_portfolio(security_recommendation)

        (new_p, updated) = portfolio_mgr_svc.update_portfolio(
            portfolio, security_recommendation, 100)

        '''
            ensure that portfolio contains all securitie from the recommendation set
        '''

        self.assertTrue(updated)
        self.assertEqual(len(new_p.model['current_portfolio'][
                         'securities']), len(security_recommendation.model['securities_set']))
        self.assertEqual(len(new_p.model['securities_set']), 0)
예제 #17
0
    def test_generate_test_instructions_no_positions(self):
        portfolio = Portfolio.from_dict(self.base_portfolio)
        broker = Broker()
        (sell_list, buy_list) = broker._generate_trade_instructions({},
                                                                    portfolio)

        self.assertListEqual(sell_list, [])
        self.assertListEqual(buy_list, ['BA', 'GE', 'XOM'])
예제 #18
0
    def test_reconcile_portfolio_mismatching_quantity(self):
        pfolio = deepcopy(self.base_portfolio)

        pfolio['current_portfolio']['securities'][0]['quantity'] = 999

        portfolio = Portfolio.from_dict(pfolio)
        broker = Broker()
        self.assertFalse(
            broker.reconcile_portfolio(self.base_positions, portfolio))
    def test_reprice_unfilled_order(self):
        portfolio_dict = {
            "portfolio_id":
            "xxx",
            "set_id":
            "yyy",
            "creation_date":
            "2020-04-14T12:20:50.219487+00:00",
            "price_date":
            "2020-03-31T04:00:00+00:00",
            "current_portfolio": {
                "securities": [{
                    "ticker_symbol": "INTC",
                    "quantity": 100,
                    "purchase_date": "2020-03-31T04:00:00+00:00",
                    "purchase_price": 0,
                    "current_price": 0,
                    "current_returns": 0,
                    "trade_state": "UNFILLED",
                    "order_id": None
                }]
            },
            "securities_set": [{
                "ticker_symbol": "AAPL",
                "analysis_price": 0,
                "current_price": 0,
                "current_returns": 0
            }]
        }

        portfolio = Portfolio.from_dict(portfolio_dict)

        with patch.object(intrinio_data,
                          'get_latest_close_price',
                          return_value=('2020-04-30', 101)):

            now = datetime.now()

            portfolio.reprice(now)

            self.assertEqual(
                portfolio.model["current_portfolio"]["securities"][0]
                ["current_price"], 101)
            self.assertEqual(
                round(
                    portfolio.model["current_portfolio"]["securities"][0]
                    ["current_returns"], 2), 0)

            self.assertEqual(
                portfolio.model["securities_set"][0]["current_price"], 101)
            self.assertEqual(
                round(portfolio.model["securities_set"][0]["current_returns"],
                      2), 0)

            self.assertEqual(
                portfolio.model["price_date"],
                util.date_to_iso_utc_string(parser.parse('2020-04-30')))
예제 #20
0
    def test_reconcile_portfolio_mismatching_ticker(self):
        pfolio = deepcopy(self.base_portfolio)
        pos = deepcopy(self.base_positions)

        pfolio['current_portfolio']['securities'][0]['ticker_symbol'] = 'XXX'

        with patch.object(td_ameritrade, 'login', return_value=None):
            portfolio = Portfolio.from_dict(pfolio)
            broker = Broker()
            self.assertFalse(broker.reconcile_portfolio(pos, portfolio))
예제 #21
0
    def test_synchronize_portfolio_all_positions_filled(self):
        portfolio = Portfolio.from_dict(self.base_portfolio)
        broker = Broker()
        broker.synchronize_portfolio(self.base_positions, portfolio)

        for sec in portfolio.model['current_portfolio']['securities']:
            self.assertEqual(sec['trade_state'], 'FILLED')
            self.assertEqual(
                sec['purchase_price'], self.base_positions['equities'][
                    sec['ticker_symbol']]['averagePrice'])
예제 #22
0
    def test_reconcile_portfolio_fewer_positions(self):
        pfolio = deepcopy(self.base_portfolio)
        pos = deepcopy(self.base_positions)

        del pfolio['current_portfolio']['securities'][0]

        with patch.object(td_ameritrade, 'login', return_value=None):

            portfolio = Portfolio.from_dict(pfolio)
            broker = Broker()
            self.assertFalse(broker.reconcile_portfolio(pos, portfolio))
    def test_update_portfolio_empty_portfolio(self):
        security_recommendation = SecurityRecommendationSet.from_dict(
            self.sr_dict)
        portfolio = Portfolio()
        portfolio.create_empty_portfolio(security_recommendation)

        (new_p, updated) = portfolio_mgr_svc.update_portfolio(
            portfolio, security_recommendation, 1)

        '''
            ensure that
            1) portfolio is updated
            2) portfolio contains 1 security
            3) portfolio contains nothing in the security set
        '''

        self.assertTrue(updated)
        self.assertEqual(
            len(new_p.model['current_portfolio']['securities']), 1)
        self.assertEqual(len(new_p.model['securities_set']), len(
            security_recommendation.model['securities_set']) - 1)
예제 #24
0
    def test_reconcile_portfolio_matching(self):
        portfolio = deepcopy(self.base_portfolio)

        # this is the bare minimum required to reconcile the portfolio
        for sec in portfolio['current_portfolio']['securities']:
            sec['quantity'] = 1
            sec['trade_state'] = 'FILLED'

        portfolio = Portfolio.from_dict(portfolio)
        broker = Broker()
        self.assertTrue(
            broker.reconcile_portfolio(self.base_positions, portfolio))
예제 #25
0
    def test_trade_buy_failed_trades(self):

        buy_positions = [('BA', 1.0), ('GE', 1.0), ('XOM', 1.0)]

        # portfolio has 3 positions
        portfolio = deepcopy(self.base_portfolio)

        portfolio = Portfolio.from_dict(portfolio)

        with patch.object(td_ameritrade, 'place_order', side_effect=[
                'order-1', 'order-2', 'order-3']), \
                patch.object(td_ameritrade, 'list_recent_orders', return_value={
                    "order-1": {
                        "status": "FILLED",
                        "symbol": "BA",
                        "quantity": 1,
                        "closeTime": "2020-05-04T03:21:04+0000",
                        "tag": "AA_myuser"
                    },
                    "order-2": {
                        "status": "FILLED",
                        "symbol": "GE",
                        "quantity": 1,
                        "closeTime": "2020-05-04T03:21:04+0000",
                        "tag": "AA_myuser"
                    },
                    "order-3": {
                        "status": "UNKNOWN",
                        "symbol": "XOM",
                        "quantity": 1,
                        "closeTime": "2020-05-04T03:21:04+0000",
                        "tag": "AA_myuser"
                    },
                }):

            broker = Broker()
            self.assertTrue(broker.trade('BUY', buy_positions, portfolio))

            pos = portfolio.get_position('BA')
            self.assertEqual(pos['trade_state'], 'FILLED')
            self.assertEqual(pos['quantity'], 1)
            self.assertIsNotNone(pos['purchase_date'])

            pos = portfolio.get_position('GE')
            self.assertEqual(pos['trade_state'], 'FILLED')
            self.assertEqual(pos['quantity'], 1)
            self.assertIsNotNone(pos['purchase_date'])

            pos = portfolio.get_position('XOM')
            self.assertEqual(pos['trade_state'], 'UNFILLED')
            self.assertEqual(pos['quantity'], 0)
            self.assertIsNone(pos['purchase_date'])
예제 #26
0
    def test_generate_test_instructions_with_buys(self):
        positions = deepcopy(self.base_positions)
        del positions['equities']['GE']
        del positions['equities']['XOM']

        portfolio = Portfolio.from_dict(self.base_portfolio)

        broker = Broker()
        (sell_list,
         buy_list) = broker._generate_trade_instructions(positions, portfolio)

        self.assertListEqual(sell_list, [])
        self.assertListEqual(buy_list, ['GE', 'XOM'])
예제 #27
0
    def test_synchronize_portfolio_no_boker_positions_filled(self):
        portfolio = Portfolio.from_dict(self.base_portfolio)
        broker = Broker()
        broker.synchronize_portfolio(
            {
                'equities': {},
                'cash': {
                    'cashAvailableForTrading': 100
                }
            }, portfolio)

        for sec in portfolio.model['current_portfolio']['securities']:
            self.assertEqual(sec['trade_state'], 'UNFILLED')
예제 #28
0
    def test_generate_test_instructions_with_sells(self):
        portfolio = deepcopy(self.base_portfolio)
        del portfolio['current_portfolio']['securities'][2]
        del portfolio['current_portfolio']['securities'][1]

        portfolio = Portfolio.from_dict(portfolio)

        broker = Broker()
        (sell_list, buy_list) = broker._generate_trade_instructions(
            self.base_positions, portfolio)

        self.assertListEqual(sell_list, [('GE', 1), ('XOM', 1)])
        self.assertListEqual(buy_list, [])
예제 #29
0
def parse_trade_data(trade_data_list):
    trades = []

    for trade_data in trade_data_list:
        if len(trade_data['STOCK CODE']) > 0:  # check that row is not empty
            trade = Trade(asset_name=trade_data['STOCK CODE'],
                          entry_date=trade_data['BUY DATE'],
                          exit_date=trade_data['SELL DATE'],
                          buy_price=trade_data['BUY PRICE'],
                          number_of_shares=trade_data['NUMBER OF SHARES'])
            if trade.data_fetch_successful:
                trades.append(trade)

    portfolio = Portfolio(trades)
    return portfolio
예제 #30
0
    def test_synchronize_portfolio_all_extra_broker_positions(self):
        portfolio = Portfolio.from_dict(self.base_portfolio)
        positions = deepcopy(self.base_positions)
        broker = Broker()
        broker.synchronize_portfolio(positions, portfolio)

        positions['equities']['XXX'] = {
            'longQuantity': 1.0,
            'averagePrice': 10.0,
            'marketValue': 10.0
        }

        for sec in portfolio.model['current_portfolio']['securities']:
            self.assertEqual(sec['trade_state'], 'FILLED')
            self.assertEqual(
                sec['purchase_price'],
                positions['equities'][sec['ticker_symbol']]['averagePrice'])