def __init__(self, trading_sessions, capital_base, data_frequency): if len(trading_sessions): start = trading_sessions[0] else: start = None # Have some fields of the portfolio changed? This should be accessed # through ``self._dirty_portfolio`` self.__dirty_portfolio = False self._immutable_portfolio = zp.Portfolio(start, capital_base) self._portfolio = zp.MutableView(self._immutable_portfolio) self.daily_returns_series = pd.Series( np.nan, index=trading_sessions, ) # Get a view into the storage of the returns series. Metrics # can access this directly in minute mode for performance reasons. self.daily_returns_array = self.daily_returns_series.values self._previous_total_returns = 0 # this is a component of the cache key for the account self._position_stats = None # Have some fields of the account changed? self._dirty_account = True self._immutable_account = zp.Account() self._account = zp.MutableView(self._immutable_account) # The broker blotter can override some fields on the account. This is # way to tangled up at the moment but we aren't fixing it today. self._account_overrides = {} self.position_tracker = PositionTracker(data_frequency) self._processed_transactions = {} self._orders_by_modified = {} self._orders_by_id = OrderedDict() # Keyed by asset, the previous last sale price of positions with # payouts on price differences, e.g. Futures. # # This dt is not the previous minute to the minute for which the # calculation is done, but the last sale price either before the period # start, or when the price at execution. self._payout_last_sale_prices = {} self.fees = { 'interest': 0., 'manager_fees': 0., }
def _get_positions_from_broker(self): """ get the positions from the broker and update zipline objects ( the ledger ) should be used once at startup and once every time we want to refresh the positions array """ cur_pos_in_tracker = self.metrics_tracker.positions positions = self._api.list_positions() for ap_position in positions: # ap_position = positions[symbol] try: z_position = zp.Position( zp.InnerPosition(symbol_lookup(ap_position.symbol))) editable_position = zp.MutableView(z_position) except SymbolNotFound: # The symbol might not have been ingested to the db therefore # it needs to be skipped. log.warning( 'Wanted to subscribe to %s, but this asset is probably not ingested' % ap_position.symbol) continue if int(ap_position.qty) == 0: continue editable_position._underlying_position.amount = int( ap_position.qty) editable_position._underlying_position.cost_basis = float( ap_position.avg_entry_price) editable_position._underlying_position.last_sale_price = float( ap_position.current_price) editable_position._underlying_position.last_sale_date = self._api.get_last_trade( ap_position.symbol).timestamp self.metrics_tracker.update_position( z_position.asset, amount=z_position.amount, last_sale_price=z_position.last_sale_price, last_sale_date=z_position.last_sale_date, cost_basis=z_position.cost_basis) # now let's sync the positions in the internal zipline objects position_names = [p.symbol for p in positions] assets_to_update = [ ] # separate list to not change list while iterating for asset in cur_pos_in_tracker: if asset.symbol not in position_names: assets_to_update.append(asset) for asset in assets_to_update: # deleting object from the metrics_tracker as its not in the portfolio self.metrics_tracker.update_position(asset, amount=0) # for some reason, the metrics tracker has self.positions AND self.portfolio.positions. let's make sure # these objects are consistent self.metrics_tracker._ledger._portfolio.positions = self.metrics_tracker.positions