def handle_data(context, data): cash = context.portfolio.cash target_hodl_value = TARGET_HODL_RATIO * context.portfolio.starting_cash reserve_value = RESERVE_RATIO * context.portfolio.starting_cash # Cancel any outstanding orders orders = get_open_orders(context.asset) or [] for order in orders: cancel_order(order) # Stop buying after passing the reserve threshold if cash <= reserve_value: context.is_buying = False # Retrieve current asset price from pricing data price = data[context.asset].price # Check if still buying and could (approximately) afford another purchase if context.is_buying and cash > price: # Place order to make position in asset equal to target_hodl_value order_target_value( context.asset, target_hodl_value, limit_price=price * 1.1, stop_price=price * 0.9, ) record( price=price, cash=cash, starting_cash=context.portfolio.starting_cash, leverage=context.account.leverage, )
def cancel_all_orders(context): # only orders placed/managed by the algo are cancelled orders = context.blotter.open_orders[context.SYMBOL] for o in orders: log.info(f"Cancelling order: {o.id}") try: cancel_order(o, context.SYMBOL) except Exception as e: log.info(f"Failed to cancel order because: {e}") finalize(context)
def rebalance(context, data): # To make market decisions, we're calculating the token's # moving average for the last 5 days. # We get the price history for the last 5 days. price_history = data.history(context.asset, fields='price', bar_count=5, frequency='1d') # Then we take an average of those 5 days. average_price = price_history.mean() # We also get the coin's current price. price = data.current(context.asset, 'price') # Cancel any outstanding orders orders = get_open_orders(context.asset) or [] for order in orders: cancel_order(order) # If our coin is currently listed on a major exchange if data.can_trade(context.asset): # If the current price is 1% above the 5-day average price, # we open a long position. If the current price is below the # average price, then we want to close our position to 0 shares. if price > (1.01 * average_price): # Place the buy order (positive means buy, negative means sell) order_target_percent(context.asset, .99) log.info("Buying %s" % (context.asset.symbol)) elif price < average_price: # Sell all of our shares by setting the target position to zero order_target_percent(context.asset, 0) log.info("Selling %s" % (context.asset.symbol)) # Use the record() method to track up to five custom signals. # Record Apple's current price and the average price over the last # five days. cash = context.portfolio.cash leverage = context.account.leverage record(price=price, average_price=average_price, cash=cash, leverage=leverage)
def handle_data(context, data): context.i += 1 starting_cash = context.portfolio.starting_cash target_hodl_value = context.TARGET_HODL_RATIO * starting_cash reserve_value = context.RESERVE_RATIO * starting_cash # Cancel any outstanding orders orders = get_open_orders(context.asset) or [] for order in orders: cancel_order(order) # Stop buying after passing the reserve threshold cash = context.portfolio.cash if cash <= reserve_value: context.is_buying = False # Retrieve current asset price from pricing data price = data.current(context.asset, 'price') # Check if still buying and could (approximately) afford another purchase if context.is_buying and cash > price: print('buying') # Place order to make position in asset equal to target_hodl_value order_target_value( context.asset, target_hodl_value, limit_price=price * 1.1, ) record( price=price, volume=data.current(context.asset, 'volume'), cash=cash, starting_cash=context.portfolio.starting_cash, leverage=context.account.leverage, )
def handle_data(context, data): # Cancel any outstanding orders orders = get_open_orders(context.asset) or [] for order in orders: cancel_order(order) # Define base price and make initial trades to achieve target investment ratio of 0.5 order_target_percent( context.asset, 0.5, ) # Retrieve current asset price from pricing data price = data[context.asset].price #Compute portfolio cumulative return Portfolio_cumulative_return = (context.portfolio.portfolio_value/context.portfolio.starting_cash-1)*100 # Save values for later inspection record(price=price, cash=context.portfolio.cash, leverage=context.account.leverage, Portfolio_cumulative_return=Portfolio_cumulative_return )
def _cancel_orders(self, order_list): if order_list is None or len(order_list) == 0: return True if self.is_live: depth = get_orderbook(order_list[0].asset) mkt_bidprc = depth['bids'][0]['rate'] mkt_askprc = depth['asks'][0]['rate'] cancelled = True for o in order_list: if o.filled != 0 and o.amount != o.filled: logging.warning('[cmx_order][cancel_orders] skip partial filled order: {}|{}|{}|{}'.format(o.id, o.limit, o.amount, o.filled)) cancelled = False continue good_to_cancel = True if self.is_live: if o.amount > 0: if o.limit >= mkt_bidprc: logging.warning('[cmx_order][cancel_orders] skip bids that is making market: {}|{} >= {}|{}|{}'.format( o.id, o.limit, mkt_bidprc, o.amount, o.filled )) good_to_cancel = False else: if o.limit <= mkt_askprc: logging.warning('[cmx_order][cancel_orders] skip asks that is making market: {}|{} <= {}|{}|{}'.format( o.id, o.limit, mkt_askprc, o.amount, o.filled )) good_to_cancel = False try: if not good_to_cancel: cancelled = False else: if self.asset.exchange == 'binance' and self.is_live: cancel_order(o, symbol = self.asset) else: cancel_order(o) except Exception as e: logging.warning(str(e)) if self.cancel_failure_map.get(o.id): self.cancel_failure_map[o.id] += 1 else: self.cancel_failure_map[o.id] = 1 if self.is_live: if self.cancel_failure_map[o.id] >= self.cancel_failure_threshold: self.ignored_orderid.append(o.id) logging.warning('[cmx_order][cancel_orders] failed to cancel order:{} in {} trials, ignore it.'.format(o.id, self.cancel_failure_threshold)) else: logging.warning('[cmx_order][cancel_orders] failed to cancel order - id:{}|exchange:{}|symbol:{}|price:{}|qty:{}, will try {} times'\ .format(o.id, o.sid.exchange, o.sid.symbol, o.limit, o.amount, \ self.cancel_failure_threshold - self.cancel_failure_map[o.id])) else: logging.warning('[cmx_order][cancel_orders] failed to cancel order - id:{}|exchange:{}|symbol:{}|price:{}|qty:{}, tried {} times'\ .format(o.id, o.sid.exchange, o.sid.symbol, o.limit, o.amount, self.cancel_failure_map[o.id])) cancelled = False return cancelled
def _process_data(self, context, data): """Called at each algo iteration Calculates indicators, processes signals, and records market and external data Arguments: context {pandas.Dataframe} -- Catalyst context object data {pandas.Datframe} -- Catalyst data object """ # catalyst dumps pickle file after handle_data called # so this call uploads the state of # the previously compelted iteration self.state.i += 1 self.log.info(f"Processing algo iteration - {self.state.i}") if not self.is_backtest and self.state.i > 1: outputs.upload_state_to_storage(self) else: self.log.debug("Skipping stats upload until catalyst writes to file") end = arrow.get(self.state.END) time_left = end.humanize(only_distance=True) self.log.debug(f"Stopping strategy in {time_left}") # the following called methods return: # True if the iteration should continued # False if the algo should not continue if not self._set_current_fields(context, data): return # To check to apply stop-loss, take-profit or keep position self.check_open_positions(context) # set date first for logging purposes self.current_date = get_datetime() if not self.fetch_history(context, data): return # Filter minute frequency self._check_minute_freq(context, data) if self.in_job: job = get_current_job() job.meta["date"] = str(self.current_date) job.save_meta() for i in context.blotter.open_orders: msg = "Canceling unfilled open order {}".format(i) self.log.info(msg) self.notify(msg) cancel_order(i) if not self.fetch_history(context, data): return self._filter_fetched_history(context, data) # ## enqueue ml models as soon as data filtered if self._ml_models: self._enqueue_ml_calcs(context, data) else: for dataset, manager in self._datasets.items(): manager.calculate(context) manager.record_data(context) for i in self._market_indicators: try: i.calculate(self.state.prices) i.record() except Exception as e: self.log.error(e) self.log.error("Error calculating {}, skipping...".format(i.name)) for i in self._ml_models: i.record() self._extra_handle(context, data) self._count_signals(context, data) if context.frame_stats: pretty_output = stats_utils.get_pretty_stats(context.frame_stats) self.log.debug(pretty_output) if not self.is_backtest: outputs.save_stats_to_storage(self) self.state.dump_to_context(context)