def __load_market_info(self): market_info = self.rh_session.market_info() if "opens_at" not in market_info or not market_info[ "opens_at"] or "closes_at" not in market_info or not market_info[ "closes_at"]: market_info = self.rh_session.get_url_content_json( market_info["next_open_hours"]) self.market_info = market_info # self.market_opens_at = datetime.now().replace(hour=8, minute=30, second=0, microsecond=0) # utc_to_local(datetime.strptime(market_info["opens_at"], "%Y-%m-%dT%H:%M:%SZ")) self.market_opens_at = utc_to_local( datetime.strptime(market_info["opens_at"], "%Y-%m-%dT%H:%M:%SZ")) self.market_closes_at = utc_to_local( datetime.strptime(market_info["closes_at"], "%Y-%m-%dT%H:%M:%SZ")) current_time = datetime.now() if (current_time >= self.market_opens_at) and (current_time < self.market_closes_at): self.is_market_open = True else: self.is_market_open = False log.debug( "market opens_at=%s, closes_at=%s, now=%s, is_market_open=%s" % (self.market_opens_at, self.market_closes_at, current_time, self.is_market_open))
def _build_order_object(self, result, symbol=None): status = self._order_status_map[result["state"]] # log.debug(result) if not symbol: instrument = self.rh_session.get_url_content_json(result["instrument"]) symbol = instrument["symbol"] order = Order(result["id"]) order.status = status order.created = utc_to_local(datetime.strptime(result["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ")) order.updated = utc_to_local(datetime.strptime(result["updated_at"], "%Y-%m-%dT%H:%M:%S.%fZ")) order.stop = None order.limit = None if result["trigger"] == "stop": order.stop = float(result["stop_price"]) if result["type"] == "limit": order.limit = float(result["price"]) order.amount = int(float(result["quantity"])) if result["side"] == "sell": order.amount = -order.amount order.symbol = symbol order.filled = int(float(result["cumulative_quantity"])) if result["side"] == "sell": order.filled = -order.filled order.commission = float(result["fees"]) order.rejected_reason = result["reject_reason"] order.time_in_force = result["time_in_force"] return order
def _get_last_filled_order_by_side(self, security): latest_buy_order = None latest_sell_order = None order_data = self.rh_session.order_history() # log.info("order_data: %s" % order_data) if order_data and "results" in order_data: for result in order_data["results"]: status = self._order_status_map[result["state"]] if status not in [1]: # or result["side"] != side: # not open order continue instrument = self.rh_session.get_url_content_json( result["instrument"]) symbol = instrument["symbol"] if security and security.symbol != symbol: # not for the the security desired continue if result["side"] == "buy": if not latest_buy_order: latest_buy_order = self._build_order_object( result, symbol) continue updated = utc_to_local( datetime.strptime(result["updated_at"], "%Y-%m-%dT%H:%M:%S.%fZ")) if latest_buy_order.updated > updated: continue latest_buy_order = result if result["side"] == "sell": if not latest_sell_order: latest_sell_order = self._build_order_object( result, symbol) continue updated = utc_to_local( datetime.strptime(result["updated_at"], "%Y-%m-%dT%H:%M:%S.%fZ")) if latest_sell_order.updated > updated: continue latest_sell_order = result return {"sell": latest_sell_order, "buy": latest_buy_order}
def __load_profile_info(self): pos_infos = self.rh_session.positions() port_info = self.rh_session.portfolios() acct_info = self.rh_session.get_account() # log.info("pos_infos:%s" % pos_infos) # log.info("account_info:%s" % acct_info) # log.info("port_info:%s" % port_info) unsettled_funds = float(acct_info["unsettled_funds"]) market_value = float(port_info["market_value"]) equity = float(port_info["equity"]) yesterday_equity = float(port_info["equity_previous_close"]) uncleared_deposits = float(acct_info["uncleared_deposits"]) cash_held_for_orders = float(acct_info["cash_held_for_orders"]) cash = float(acct_info["cash"]) total_cash = cash + unsettled_funds portfolio_value = equity buying_power = equity - market_value - cash_held_for_orders if not self._starting_cash: self._starting_cash = portfolio_value if not self._start_date: self._start_date = datetime.now() returns = 0 if self._starting_cash and self._starting_cash > 0: returns = (portfolio_value - self._starting_cash) / self._starting_cash long_position_value = 0 short_position_value = 0 unrealized_pl = 0 positions = {} # log.info("pos: %s" % pos_infos["results"]) if pos_infos and pos_infos["results"]: for result in pos_infos["results"]: amount = int(float(result["quantity"])) if amount == 0: continue log.info("pos_infos:%s" % result) instrument = self.rh_session.get_url_content_json( result["instrument"]) symbol = instrument["symbol"] security = self.fetch_and_build_security(symbol, sec_detail=instrument) # last_price = self.current(security, field="price") last_price = float( self.rh_session.last_trade_price(symbol)[0][0]) log.debug(last_price) # if not last_price: # Lets try again # last_price = self.current(security, field="price") if not last_price and security in self._security_last_known_price: last_price = self._security_last_known_price[security] self._security_last_known_price[security] = last_price created = utc_to_local( datetime.strptime(result["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ")) updated = utc_to_local( datetime.strptime(result["updated_at"], "%Y-%m-%dT%H:%M:%S.%fZ")) cost_basis = float(result["average_buy_price"]) position = Position(amount, cost_basis, last_price, created, updated) if "intraday_quantity" in result: position.day_amount = int( float(result["intraday_quantity"])) if "intraday_average_buy_price" in result: position.day_cost_basis = int( float(result["intraday_average_buy_price"])) positions[security] = position # position_value = position_value+(cost_basis*amount) if amount > 0: unrealized_pl = unrealized_pl + ((last_price * amount) - (cost_basis * amount)) long_position_value = long_position_value + (cost_basis * amount) else: unrealized_pl = unrealized_pl + ( (cost_basis * np.abs([amount])[0]) - (last_price * np.abs([amount])[0])) short_position_value = long_position_value + ( cost_basis * np.abs([amount])[0]) pnl = equity - uncleared_deposits - yesterday_equity # unrealized_pl + unsettled_funds leverage = 0 net_leverage = 0 if portfolio_value > 0: leverage = (long_position_value + short_position_value) / portfolio_value net_leverage = market_value / portfolio_value portfolio = Portfolio() portfolio.capital_used = np.abs([ (short_position_value - long_position_value) ])[0] portfolio.cash = total_cash portfolio.pnl = pnl portfolio.positions = positions portfolio.portfolio_value = portfolio_value portfolio.positions_value = market_value portfolio.returns = returns portfolio.starting_cash = self._starting_cash portfolio.start_date = self._start_date self.context.portfolio = portfolio account = Account() # account.accrued_interest=acct_info account.available_funds = portfolio_value account.buying_power = buying_power account.cushion = total_cash / portfolio_value account.day_trades_remaining = float("inf") account.equity_with_loan = portfolio_value account.excess_liquidity = port_info["excess_margin"] account.initial_margin_requirement = float( acct_info["margin_balances"]["margin_limit"] ) if "margin_balances" in acct_info and "margin_limit" in acct_info[ "margin_balances"] else 0 account.leverage = leverage account.maintenance_margin_requirement = portfolio_value - float( port_info["excess_margin"]) account.net_leverage = net_leverage account.net_liquidation = portfolio_value account.settled_cash = cash account.total_positions_value = market_value if "unallocated_margin_cash" in acct_info: account.unallocated_margin_cash = float( acct_info["unallocated_margin_cash"]) self.context.account = account
def _time_interval_processor(self): now = datetime.now() if now.weekday() not in [5, 6]: # if now.weekday() not in [6]: log.debug("In time interval processor") temp_datetime = datetime.now() self._active_datetime = temp_datetime.replace(second=0, microsecond=0) market_open_temp = self.is_market_open self._current_security_bars = {} if not self._load_all_data(): # Load Data Failed... we can't go further until we get fresh data... bad things can happend if algo operate with stale data. # Set reload data again in 1 minute. log.debug( "Data retrieval was adnormal we'll check again next minute to try again " ) _set_trigger_timer( minute_interval=1, callback_function=self._time_interval_processor) return schedule.CancelJob # update context status self.context.is_market_open = self.is_market_open if (not self._initialized or not market_open_temp) and self.is_market_open: # if market was not open and is now open... initialize algo try: if hasattr(self.active_algo, 'on_market_open'): self.active_algo.on_market_open( self.context, self.friar_data) # self.active_algo.handle_data(self.context, self.friar_data) except Exception as inst: log.error("Error occurred while invoking initialize: %s " % inst) traceback.print_exc() if self._data_frequency == "1d": # with this frequency, it's a market closed last update whenever this method is call self._market_closed_lastupdate = True elif self._data_frequency == "1h": minutes_after_open_time = self.market_opens_at + timedelta( hours=1) minutes_after_open_time = minutes_after_open_time.replace( minute=0, second=0, microsecond=0) elif self._data_frequency == "15m": minutes_after_open_time = self.market_opens_at + timedelta( minutes=15) minutes_after_open_time = minutes_after_open_time.replace( second=0, microsecond=0) elif self._data_frequency == "5m": minutes_after_open_time = self.market_opens_at + timedelta( minutes=5) minutes_after_open_time = minutes_after_open_time.replace( second=0, microsecond=0) else: minutes_after_open_time = self.market_opens_at + timedelta( minutes=1) # Adding one more call if market_open_temp and not self.is_market_open: # If market used to be open and at this update is now closed, we want to call handle_data one more time self._market_closed_lastupdate = True # we want the algo to be called one more time. current_time = datetime.now() try: if ( self.is_market_open and current_time >= minutes_after_open_time ) or self._market_closed_lastupdate: # current_time < minutes_after_close_time: self.active_algo.handle_data(self.context, self.friar_data) if self._market_closed_lastupdate: self._market_closed_lastupdate = False except Exception as e: log.error("Error occurred while invoking handle_data: %s " % e) traceback.print_exc() if self._data_frequency == "1d": direct_time = self.market_closes_at if datetime.now() >= direct_time: market_info = self.rh_session.get_url_content_json( self.market_info["next_open_hours"]) direct_time = utc_to_local( datetime.strptime(market_info["closes_at"], "%Y-%m-%dT%H:%M:%SZ")) direct_time = direct_time + timedelta( minutes=5) # wait 5 minutes after market closes elif self._data_frequency == "1h": if not self.is_market_open and datetime.now( ) < self.market_opens_at: direct_time = self.market_opens_at elif not self.is_market_open and datetime.now( ) > self.market_closes_at: market_info = self.rh_session.get_url_content_json( self.market_info["next_open_hours"]) direct_time = utc_to_local( datetime.strptime(market_info["opens_at"], "%Y-%m-%dT%H:%M:%SZ")) else: direct_time = datetime.now() + timedelta( hours=1) # update every hour direct_time = direct_time.replace(minute=0, second=0, microsecond=0) elif self._data_frequency == "15m": if not self.is_market_open and datetime.now( ) < self.market_opens_at: direct_time = self.market_opens_at elif not self.is_market_open and datetime.now( ) > self.market_closes_at: market_info = self.rh_session.get_url_content_json( self.market_info["next_open_hours"]) direct_time = utc_to_local( datetime.strptime(market_info["opens_at"], "%Y-%m-%dT%H:%M:%SZ")) else: now = datetime.now() multiples = int(now.minute / 15) diff = now.minute - (multiples * 15) direct_time = now + timedelta(minutes=(15 - diff)) # direct_time = datetime.now() + timedelta(minutes=15) # update every 15 minutes direct_time = direct_time.replace(second=0, microsecond=0) elif self._data_frequency == "5m": if not self.is_market_open and datetime.now( ) < self.market_opens_at: direct_time = self.market_opens_at elif not self.is_market_open and datetime.now( ) > self.market_closes_at: market_info = self.rh_session.get_url_content_json( self.market_info["next_open_hours"]) direct_time = utc_to_local( datetime.strptime(market_info["opens_at"], "%Y-%m-%dT%H:%M:%SZ")) else: now = datetime.now() multiples = int(now.minute / 5) diff = now.minute - (multiples * 5) direct_time = now + timedelta(minutes=(5 - diff)) # direct_time = datetime.now() + timedelta(minutes=5) # update every 5 minutes direct_time = direct_time.replace(second=0, microsecond=0) else: direct_time = datetime.now() + timedelta( minutes=1) # update every minute direct_time = direct_time.replace(second=0, microsecond=0) # log.debug("Interval Processing Done - Next Trigger %s" % direct_time) _set_trigger_timer(callback_function=self._time_interval_processor, direct_time=direct_time) return schedule.CancelJob
def _load_quotes(symbol, frequency, interval, period_factor, period, bar_count, field, wait_time=None): target_url = "https://finance.google.com/finance/getprices?i=" + str( interval) + "&p=" + str( period_factor) + period + "&f=d,o,h,l,c,v&q=" + symbol # log.debug(target_url) # data = urlopen(target_url, timeout=10) # it's a file like object and works just like a file bars = None unix_date = None req = urllib.request.Request(target_url) with urllib.request.urlopen(req) as response: if wait_time: log.debug("About to sleep") time.sleep(wait_time) for line in response: # files are iterable line = line.decode("utf-8").strip() # print (line) if not unix_date and not line.startswith("a"): continue if line.startswith("TIMEZONE_OFFSET"): print("timezone change: %s" % line) continue offset = 0 (date, close, high, low, open, volume) = line.split(',') if date.startswith("a"): unix_date = int(date.replace("a", "")) offset = 0 else: offset = int(date) quote_date = datetime.utcfromtimestamp(unix_date + (offset * interval)) if frequency == "1m" or frequency == "5m" or frequency == "15m" or frequency == "1h": quote_date = utc_to_local(quote_date) bar = pd.DataFrame(index=pd.DatetimeIndex([quote_date]), data={ 'price': float(close), 'open': float(open), 'high': float(high), 'low': float(low), 'close': float(close), 'volume': int(volume) }) # print(close) if bars is None: bars = bar else: bars = bars.append(bar) if bars is None: # log.warn("Unexpected, could not retrieve quote for security (%s) " % symbol) quote_date = datetime.now() quote_date = quote_date.replace(second=0, microsecond=0) bars = pd.DataFrame(index=pd.DatetimeIndex([quote_date]), data={ 'price': float("nan"), 'open': float("nan"), 'high': float("nan"), 'low': float("nan"), 'close': float("nan"), 'volume': int(0) }) # return bars bars = bars.tail(bar_count) if field: bars = bars[field] return bars