Exemplo n.º 1
0
    def test_positions_summary_not_cash_account(self):
        response = deepcopy(self.td_account_response)
        response['securitiesAccount']['type'] = 'MARGIN'

        with patch.object(td_ameritrade, 'get_credentials',
                          return_value=("aaa", "bbb", "ccc")), \
                patch.object(td_ameritrade, 'login', return_value=None),\
                patch.object(td_ameritrade, 'request', return_value=(None, response)):

            with self.assertRaises(ValidationError):
                td_ameritrade.positions_summary()
Exemplo n.º 2
0
    def materialize_portfolio(self, broker_positions: dict, portfolio: object):
        '''
            Materializes the porfolio by executing the trades necessary to do so.
            Specifically:

            1) Sell all securities not in the portfolio
            2) Buy all existing securities not already owned
        '''

        (sell_trades, buy_trades) = self._generate_trade_instructions(
            broker_positions, portfolio)

        if len(sell_trades) > 0:
            if (self.trade('SELL', sell_trades, None) == False):
                log.warning(
                    "There was error unwinding positions. Portfolio could not be materialized"
                )
                raise TradeError(
                    "Could not unwind (sell) all positions from portfolio",
                    None, None)
        '''
            Get the cash available for trading and split it evenly acorss all securities
            to be bought.
        '''
        if len(buy_trades) > 0:
            current_broker_positions = td_ameritrade.positions_summary()
            try:
                available_cash = current_broker_positions['cash'][
                    'cashAvailableForTrading']
            except KeyError:
                available_cash = 0

            # trade 90% of available cash
            trade_dollar_amount = (available_cash / len(buy_trades)) * 0.9

            buy_instructions = []
            for buy_ticker in buy_trades:
                latest_price = td_ameritrade.get_latest_equity_price(
                    buy_ticker)

                shares = int(trade_dollar_amount / latest_price)

                if shares > 0:
                    buy_instructions.append((buy_ticker, shares))
                else:
                    log.warning(
                        "Will not purchase %s, because there aren't enough funds"
                        % buy_ticker)

            if len(buy_instructions) == 0:
                log.warning("Could not afford to purchase any securities")
                return

            if self.trade('BUY', buy_instructions, portfolio) == False:
                log.warning(
                    "There was an error adding positions to the portoflio. Portfolio could not be materialized"
                )
        else:
            log.info("There are no securities to buy")
Exemplo n.º 3
0
    def test_positions_summary_valid_response(self):
        response = deepcopy(self.td_account_response)

        with patch.object(td_ameritrade, 'get_credentials',
                          return_value=("aaa", "bbb", "ccc")), \
                patch.object(td_ameritrade, 'login', return_value=None),\
                patch.object(td_ameritrade, 'request', return_value=(None, response)):

            summary = td_ameritrade.positions_summary()

            self.assertDictEqual(summary, {
                'cash': {'cashAvailableForTrading': 1000.0},
                'equities': {'SPY': {'averagePrice': 100,
                                     'longQuantity': 1.0,
                                     'marketValue': 100}
                             }
            })
Exemplo n.º 4
0
    def test_positions_summary_no_positions(self):
        '''
            Tests that when positions are missing from the response, no
            exceptions are thrown
        '''
        response = deepcopy(self.td_account_response)
        del response['securitiesAccount']['positions']

        with patch.object(td_ameritrade, 'get_credentials',
                          return_value=("aaa", "bbb", "ccc")), \
                patch.object(td_ameritrade, 'login', return_value=None),\
                patch.object(td_ameritrade, 'request', return_value=(None, response)):

            summary = td_ameritrade.positions_summary()

            self.assertDictEqual(summary, {
                'cash': {'cashAvailableForTrading': 1000.0},
                'equities': {}
            })
Exemplo n.º 5
0
def main():
    """
        Main function of this script
    """
    try:
        #(app_ns, portfolio_size) = parse_params()
        (app_ns, portfolio_size) = ('sa', 3)

        log.info("Application Parameters")
        log.info("-app_namespace: %s" % app_ns)
        log.info("-portfolio_size: %d" % portfolio_size)

        # test all connectivity upfront, so if there any issues
        # the problem becomes more apparent
        connector_test.test_all_connectivity()

        (current_portfolio,
         security_recommendation) = portfolio_mgr_svc.get_service_inputs(app_ns)

        log.info("Loaded recommendation set id: %s" %
                 security_recommendation.model['set_id'])

        if current_portfolio is None:
            log.info("Creating new portfolio")
            current_portfolio = Portfolio(None)
            current_portfolio.create_empty_portfolio(security_recommendation)
        else:
            log.info("Repricing portfolio")
            current_portfolio.reprice(datetime.now())

        (updated_portfolio, updated) = portfolio_mgr_svc.update_portfolio(
            current_portfolio, security_recommendation, portfolio_size)

        # See if there is anything that needs to be traded
        market_open = td_ameritrade.equity_market_open(datetime.now())

        if market_open == True:
            broker = Broker()
            broker.cancel_all_open_orders()

            log.info("Market is open. Looking for trading opportunities")
            current_positions = td_ameritrade.positions_summary()

            try:
                if broker.reconcile_portfolio(current_positions, updated_portfolio) == False:
                    log.info(
                        "Portfolio is not in sync with brokerage account positions. Positions will be rebalanced")

                broker.materialize_portfolio(
                    current_positions, updated_portfolio)
            finally:
                updated_positions = td_ameritrade.positions_summary()
                broker.synchronize_portfolio(
                    updated_positions, updated_portfolio)

                updated_portfolio.recalc_returns()
                broker.cancel_all_open_orders()
        else:
            log.info("Market is closed. Nothing to trade")

        log.info("updated portfolio: %s" %
                 util.format_dict(updated_portfolio.to_dict()))

        log.info("Saving updated portfolio")
        updated_portfolio.save_to_s3(
            app_ns, constants.S3_PORTFOLIO_OBJECT_NAME)

        portfolio_mgr_svc.publish_current_returns(
            updated_portfolio, updated, app_ns)

    except Exception as e:
        stack_trace = traceback.format_exc()
        log.error("Could run script, because: %s" % (str(e)))
        log.error(stack_trace)

        aws_service_wrapper.notify_error(e, "Portfolio Manager Service",
                                         stack_trace, app_ns)