def _handle_buy_sell_decision(context, data, signal, price): orders = get_open_orders(context.asset) if len(orders) > 0: log.info('skipping bar until all open orders execute') return positions = context.portfolio.positions if context.position is None and context.asset in positions: position = positions[context.asset] context.position = dict( cost_basis=position['cost_basis'], amount=position['amount'], stop=None ) # action = None if context.position is not None: cost_basis = context.position['cost_basis'] amount = context.position['amount'] log.info( 'found {amount} positions with cost basis {cost_basis}'.format( amount=amount, cost_basis=cost_basis ) ) stop = context.position['stop'] target = cost_basis * (1 + context.TARGET) if price >= target: context.position['cost_basis'] = price context.position['stop'] = context.STOP stop_target = context.STOP_LOSS if stop is None else context.STOP if price < cost_basis * (1 - stop_target): log.info('executing stop loss') order( asset=context.asset, amount=-amount, limit_price=price * (1 - context.SLIPPAGE_ALLOWED), ) # action = 0 context.position = None else: if signal == 'long': log.info('opening position') buy_amount = context.MAX_HOLDINGS / price order( asset=context.asset, amount=buy_amount, limit_price=price * (1 + context.SLIPPAGE_ALLOWED), ) context.position = dict( cost_basis=price, amount=buy_amount, stop=None )
def handle_data(self, data): from catalyst.api import ( order_percent, order_target, order_target_percent, order_target_value, order_value, ) for style in [MarketOrder(), LimitOrder(10), StopOrder(10), StopLimitOrder(10, 10)]: with assert_raises(UnsupportedOrderParameters): order(self.asset, 10, limit_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order(self.asset, 10, stop_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_value(self.asset, 300, limit_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_value(self.asset, 300, stop_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_percent(self.asset, .1, limit_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_percent(self.asset, .1, stop_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_target(self.asset, 100, limit_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_target(self.asset, 100, stop_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_target_value(self.asset, 100, limit_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_target_value(self.asset, 100, stop_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_target_percent(self.asset, .2, limit_price=10, style=style) with assert_raises(UnsupportedOrderParameters): order_target_percent(self.asset, .2, stop_price=10, style=style)
def makeOrders(context, analysis): if context.asset in context.portfolio.positions: # Current position position = context.portfolio.positions[context.asset] if (position == 0): log.info('Position Zero') return # Cost Basis cost_basis = position.cost_basis log.info( 'Holdings: {amount} @ {cost_basis}'.format( amount=position.amount, cost_basis=cost_basis ) ) # Sell when holding and got sell singnal if isSell(context, analysis): profit = (context.price * position.amount) - ( cost_basis * position.amount) order_target_percent( asset=context.asset, target=0, limit_price=context.price * (1 - context.SLIPPAGE_ALLOWED), ) log.info( 'Sold {amount} @ {price} Profit: {profit}'.format( amount=position.amount, price=context.price, profit=profit ) ) else: log.info('no buy or sell opportunity found') else: # Buy when not holding and got buy signal if isBuy(context, analysis): order( asset=context.asset, amount=context.ORDER_SIZE, limit_price=context.price * (1 + context.SLIPPAGE_ALLOWED) ) log.info( 'Bought {amount} @ {price}'.format( amount=context.ORDER_SIZE, price=context.price ) )
def handle_data_api(context, data): if context.incr == 0: assert 0 not in context.portfolio.positions else: assert context.portfolio.positions[0].amount == \ context.incr, "Orders not filled immediately." assert context.portfolio.positions[0].last_sale_price == \ data.current(sid(0), "price"), \ "Orders not filled at current price." context.incr += 1 order(sid(0), 1) record(incr=context.incr)
def buy(context): position = context.portfolio.positions[context.asset] if context.portfolio.cash < context.price * context.ORDER_SIZE: log.warn( "Skipping signaled buy due to cash amount: {} < {}".format( context.portfolio.cash, (context.price * context.ORDER_SIZE) ) ) return order( asset=context.asset, amount=context.ORDER_SIZE, limit_price=context.price * (1 + context.SLIPPAGE_ALLOWED), ) log.info( "Bought {amount} @ {price}".format(amount=context.ORDER_SIZE, price=context.price) )
def split_order(self, asset, qty, limit_price): min_qty = self.context.invent_min_share residual_qty = qty if qty > 0: while residual_qty >= 2 * min_qty: order(asset, min_qty, limit_price) residual_qty -= min_qty order(asset, residual_qty, limit_price) elif qty < 0: while residual_qty <= -2 * min_qty: order(asset, -1 * min_qty, limit_price) residual_qty += min_qty order(asset, residual_qty, limit_price)
def _stop_loss_sell(self, context, position): order( asset=self.state.asset, amount=-position.amount, # limit_price=self.state.price * (1 - self.state.SLIPPAGE_ALLOWED), ) profit = (self.state.price * position.amount) - ( position.cost_basis * position.amount ) msg = "Sold {amount} @ {price} Profit: {profit}; Produced by stop-loss signal at {date}".format( amount=position.amount, price=self.state.price, profit=profit, date=get_datetime(), ) self.log.notice(msg) self.notify(dedent(msg))
def _split_order(self, qty, limit_price): min_qty = self.min_share / limit_price residual_qty = qty if qty > 0: while residual_qty >= 2 * min_qty: order(self.asset, min_qty, limit_price) residual_qty -= min_qty order(self.asset, residual_qty, limit_price) elif qty < 0: while residual_qty <= -2 * min_qty: order(self.asset, -1 * min_qty, limit_price) residual_qty += min_qty order(self.asset, residual_qty, limit_price)
def handle_data(context, data): # set context.can_buy = True, context.can_sell = False in initialize() bid_price = 999999 ask_price = 0 quantity = 100 if context.portfolio.positions[context.asset].amount != 0: print('{} @ {}'.format( context.portfolio.positions[context.asset].cost_basis, context.portfolio.positions[context.asset].amount)) if context.can_buy: if context.portfolio.positions[context.asset].amount < 1000: order(context.asset, quantity, limit_price=bid_price) else: context.can_sell = True context.can_buy = False if context.can_sell: if context.portfolio.positions[context.asset].amount > 0: order(context.asset, -1 * quantity, limit_price=ask_price) else: return
def handle_data(context, data): last3 = [] last3orig = data.history(context.asset, 'price', bar_count=3, frequency='1T') last3[:] = last3orig if context.portfolio.positions[context.asset].amount == 0: if sorted(last3) == last3: print("here") cash = context.portfolio.cash context.cur_price = data.current(context.asset, 'price') buy_amount = int( min(cash // context.cur_price, 100000 // context.cur_price)) order(context.asset, buy_amount) else: if data.current(context.asset, 'price') < .9 * context.cur_price: num = context.portfolio.positions[context.asset].amount order(context.asset, -num) if sorted(last3) != last3 and (context.cur_price * 1.15) < data.current( context.asset, 'price'): print("HERE") num = context.portfolio.positions[context.asset].amount order(context.asset, -num) record(btc=data.current(context.asset, 'price'))
def try_buy(context, data, increment): """Attempt a buy/sell. Returns false if assets or cash insufficient. Returns true if order is successfully placed. """ # INCREMENT = 5.0 is_buy = increment > 0 is_sell = increment < 0 price = data.current(context.asset, 'price') if is_buy: # increment = INCREMENT print('buy {:0.4f}{}'.format(increment, context.ASSET_NAME.split('_')[0])) if price * increment > context.portfolio.cash: print('not enough base currency buy') return False # # log.info( # 'buying position cheaper than cost basis {} < {}'.format( # price, # 'NA' # # cost_basis # ) # ) buy_price = price * (1 + context.SLIPPAGE_ALLOWED) order(asset=context.asset, amount=increment, limit_price=buy_price) context.buys.append(buy_price) return True elif is_sell: # increment = -INCREMENT print('sell {:0.4f}{}'.format(-increment, context.ASSET_NAME.split('_')[0])) if (abs(increment) > context.portfolio.positions[context.asset].amount): print('not enough asset to sell') return False sell_price = price * (1 - context.SLIPPAGE_ALLOWED) order(asset=context.asset, amount=increment, limit_price=sell_price) context.sells.append(sell_price) return True
def makeOrders(context, analysis): if context.in_long: weAreLong(context, analysis) elif context.in_short: weAreShort(context, analysis) else: if getLast(analysis, "sma_test") == 1: order(context.asset, amount=context.ORDER_SIZE) context.in_long = True context.in_short = False context.level = 1 context.cost_basis = context.price """ context.position = position """ log.info( "Bought {amount} @ {price}".format( amount=context.ORDER_SIZE, price=context.price ) )
def makeOrders(context, analysis): if context.asset in context.portfolio.positions: # Current position position = context.portfolio.positions[context.asset] if position == 0: log.info("Position Zero") return # Cost Basis cost_basis = position.cost_basis log.info("Holdings: {amount} @ {cost_basis}".format( amount=position.amount, cost_basis=cost_basis)) # Sell when holding and got sell singnal if isSell(context, analysis): profit = (context.price * position.amount) - (cost_basis * position.amount) order_target_percent( asset=context.asset, target=0, limit_price=context.price * (1 - context.SLIPPAGE_ALLOWED), ) log.info("Sold {amount} @ {price} Profit: {profit}".format( amount=position.amount, price=context.price, profit=profit)) else: log.info("no buy or sell opportunity found") else: # Buy when not holding and got buy signal if isBuy(context, analysis): order( asset=context.asset, amount=context.ORDER_SIZE, limit_price=context.price * (1 + context.SLIPPAGE_ALLOWED), ) log.info("Bought {amount} @ {price}".format( amount=context.ORDER_SIZE, price=context.price))
def handle_data(context, data): if context.index == 0: order(symbol("bat_btc"), -9.9, limit_price=0.00002630) print("blotter={}".format(context.blotter.orders)) #res = data.can_trade(sym) #history = data.history(symbol("bch_btc"), ['close'], # bar_count=11, # frequency='5T') #print('\nnow: %s\n%s' % (data.current_dt, history)) #if not hasattr(context, 'i'): # context.i = 0 #context.i += 1 #print(history) #get_order(5, return_price=True) print("open orders={}".format(get_open_orders(context.asset))) context.index += 1
def weAreLong(context, analysis): s1 = context.asset TP = context.cost_basis + context.upper SL = context.cost_basis - context.lower Crit = context.cost_basis - context.distance position = context.portfolio.positions[context.asset] log.info('We Are Long. Holdings: {amount} @ {cost_basis}'.format( amount=position.amount, cost_basis=context.cost_basis)) if context.price < Crit: order( s1, amount=-(context.ORDER_SIZE * context.multiplyBy * context.level)) context.in_long = False context.in_short = True context.level += 1 log.info('Kill Long! GO SHORT! Sold {amount} @ {price}'.format( amount=position.amount, price=context.price)) elif context.price > TP: context.in_long = False context.in_short = False context.level = 1 order_target(s1, 0) log.info('We made it! Sold {amount} @ {price}'.format( amount=position.amount, price=context.price)) elif context.price < SL: context.in_long = False context.in_short = False context.level = 1 order_target(s1, 0) log.info('We lost it all! Sold {amount} @ {price}'.format( amount=position.amount, price=context.price)) else: log.info('no buy or sell opportunity found')
def place_order(context): if context.PLACING_ORDERS: return context.PLACING_ORDERS = True if validate_balances(context): try: order_id = order(asset=context.SYMBOL, amount=ALGO_INPUTS["ORDER_AMOUNT"], limit_price=ALGO_INPUTS["ORDER_PRICE"]) log.info( f"Placed order of {ALGO_INPUTS['ORDER_AMOUNT']}@{ALGO_INPUTS['ORDER_AMOUNT']}, order id is {order_id}" ) context.PLACING_ORDERS = False except Exception as e: log.info(f"Failed to place order because: {e}") finalize(context)
def handle_data(context, data): poloneix_price = data.current(context.poloniex_trading_pair, 'price') bitfinex_price = data.current(context.bitfinex_trading_pair, 'price') binance_price = data.current(context.binance_trading_pair, 'price') slippage = 0.035 sell_p, buy_p = get_adjusted_prices(poloneix_price, slippage) sell_b, buy_p = get_adjusted_prices(bitfinex_price, slippage) #price = data.current(context.bitfinex_price, 'price') #record(price=price, # cash=context.portfolio.cash) if is_profitable_after_fees(sell_p, buy_p, context.poloniex, context.bitfinex): print('Date: {}'.format(data.current_dt)) print( 'Bitfinex Price: {}, Poloniex Price: {}, Binance Price: {}'.format( bitfinex_price, poloneix_price, binance_price)) order(asset=context.bitfinex_trading_pair, amount=1, limit_price=buy_p) order(asset=context.poloniex_trading_pair, amount=-1, limit_price=sell_p) elif is_profitable_after_fees(sell_b, buy_p, context.bitfinex, context.poloniex): print('Date: {}'.format(data.current_dt)) print( 'Bitfinex Price: {}, Poloniex Price: {}, Binance Price: {}'.format( bitfinex_price, poloneix_price, binance_price)) order(asset=context.poloniex_trading_pair, amount=-1, limit_price=buy_p) order(asset=context.bitfinex_trading_pair, amount=1, limit_price=sell_b)
def handle_data(context, data): poloniex_price = data.current(context.poloniex_trading_pair, 'price') binance_price = data.current(context.binance_trading_pair, 'price') slippage = 0.03 sell_p, buy_p = get_adjusted_prices(poloniex_price, slippage) sell_b, buy_b = get_adjusted_prices(binance_price, slippage) # print('Data: {}'.format(data.current_dt)) # print('Poloniex: {}'.format(poloniex_price)) # print('Binance: {}'.format(binance_price)) if is_profitable_after_fees(sell_p, buy_b, context.poloniex, context.binance): # Buy on binance, sell on poloniex order(asset=context.binance_trading_pair, amount=1, limit_price=binance_price) order(asset=context.poloniex_trading_pair, amount=-1, limit_price=poloniex_price) elif is_profitable_after_fees(sell_b, buy_p, context.binance, context.poloniex): # buy poloniex, sell binance order(asset=context.binance_trading_pair, amount=-1, limit_price=binance_price) order(asset=context.poloniex_trading_pair, amount=1, limit_price=poloniex_price) record( poloniex_price=poloniex_price, binance_price=binance_price, cash=context.portfolio.cash, )
def _place_buy_limit_order(self, context, amount=None, slippage=None): if amount is None: amount = self.state.ORDER_SIZE if slippage is None: slippage = self.state.SLIPPAGE_ALLOWED limit_price = self.state.price * (1 + slippage) order_total = self.state.price * amount if context.portfolio.cash < self.state.price * amount: self.log.debug( f"Skipping signaled buy due to insufficient cash: {context.portfolio.cash} < {order_total}" ) return self.log.info( f"Placing limit order for {amount} {self.state.asset} with total: {order_total}" ) order_id = None try: order_id = order( asset=self.state.asset, amount=amount, limit_price=limit_price ) msg = "Bought {amount} @ {price}".format( amount=self.state.ORDER_SIZE, price=self.state.price ) except exchange_errors.CreateOrderError as e: msg = f"Failed to make limit buy: {str(e)}" self.log.error(str(e)) self.log.warning(msg) self.notify(msg) return order_id
def handle_data(context, data): context.asset = symbol("btc_usd") current = data.history(context.asset, ['price', 'volume'], bar_count=1, frequency='1T') price = data.current(context.asset, 'price') volume = data.current(context.asset, 'volume') #pd.set_option("display.precision", 8) #print(history) context.pricing_data = context.pricing_data.append(current) context.csvwriter.writerow([ current.index[0], current.iloc[0]['price'], current.iloc[0]['volume'] ]) if context.index == 0 or context.index == 2 or context.index == 4: order(context.asset, 1) for item, orders in get_open_orders().items(): o = orders[0] get_order(o.sid) elif context.index == 6: order(context.asset, -1) elif context.index == 8: order(context.asset, -1) if context.portfolio.positions: position = context.portfolio.positions[context.asset] print("index={}".format(context.index)) print("amount={}, cost-basis={}".format(position.amount, position.cost_basis)) # # context.csvwriter.writerow([data.current_dt, # current.iloc[0]['price'], # current.iloc[0]['volume']]) #print(context.blotter.current_dt) #print(data.current_dt) context.index += 1
def handle_data(context, data): short_window = 5 #value obtained from Belinda script long_window = 24 #value obtained from Belinda script context.i += 1 if context.i < long_window: return #calculate EMA with Talib my_short_stock_series = data.history( context.asset, 'price', bar_count=short_window, frequency="1T", ) ema_short_result = talib.EMA(my_short_stock_series, timeperiod=short_window) short_ema = ema_short_result[-1] #long ema calculations is corrected based on upwork developer comment my_long_stock_series = data.history( context.asset, 'price', bar_count=long_window + 1, frequency="1T", ) ema_long_result = talib.EMA(my_long_stock_series, timeperiod=long_window) long_ema = ema_long_result[-1] price = data.current(context.asset, 'price') if context.base_price is None: context.base_price = price price_change = (price - context.base_price) / context.base_price record(price=price, cash=context.portfolio.cash, price_change=price_change, short_ema=short_ema, long_ema=long_ema) pos_amount = context.portfolio.positions[context.asset].amount orders = context.blotter.open_orders if len(orders) > 0: return if not data.can_trade(context.asset): return #sizing calculations #getting high, low, close value from history to talib.ATR function highs = data.history( context.asset, 'high', bar_count=300, frequency="1T", ).dropna() lows = data.history( context.asset, 'low', bar_count=300, frequency="1T", ).dropna() closes = data.history( context.asset, 'close', bar_count=300, frequency="1T", ).dropna() atr = talib.ATR(highs, lows, closes) #talib.ATR output is an array stop_loss_atr = atr[-1] #talib.ATR output is an array stop = stop_loss_atr #print("stop_loss_atr=", stop_loss_atr) #position size calculation based on current equity, risk and trailing stop size = context.portfolio.portfolio_value * context.risk / stop trading_avaliable = context.portfolio.portfolio_value / 0.3 / price size_aval = size if size < trading_avaliable else trading_avaliable #equal to PineScript statement, size_aval = size<trading_avaliable?size:trading_avaliable #print("size_aval=", size_aval) #trailing stop call. obtaining context.stop_price set_trailing_stop( context, data, stop) #maybe trailing stop should be calculated when order start set_trailing_stop_short(context, data, stop) #print("price=", price, "context.stop_price=", context.stop_price,"context.stop_price_short=", context.stop_price_short) #check for the long stop price and long orders are open if (pos_amount > 0): if price < context.stop_price: order_target_percent(context.asset, 0) context.stop_price = 0 #print("trailing stop") if (pos_amount < 0): if price > context.stop_price_short: order_target_percent(context.asset, 0) context.stop_price_short = 0 #print("trailing stop short") EL = short_ema > long_ema and pos_amount <= 0 ES = short_ema < long_ema and pos_amount > 0 record(EL=EL, ES=ES) if EL: order_target_percent(context.asset, 0) #close short asset order(context.asset, size_aval) #open long asset #print("long") elif ES: order_target_percent(context.asset, 0) #close long asset order(context.asset, -size_aval) #open short asset
def handle_data(context, data): """ 在每个交易周期上运行的策略 """ context.i += 1 # 记录交易周期 if context.i < LONG_WIN + 1: # 如果交易周期过短,无法计算均线,则跳过循环 log.warning('交易周期过短,无法计算指标') return if context.i % TRADE_WIN != 0: return # 获取当前周期内有效的加密货币 context.available_asset_pool = [asset for asset in context.asset_pool if asset.start_date <= data.current_dt] context.up_cross_signaled = set() # 初始化金叉的交易对集合 context.down_cross_signaled = set() # 初始化死叉的交易对集合 for asset in context.available_asset_pool: # 遍历每一个加密货币对 # 获得历史价格 frequency = '{}T'.format(TRADE_WIN) # '5T' hitory_data = data.history(asset, 'close', bar_count=LONG_WIN + 1, frequency=frequency, ) if len(hitory_data) >= LONG_WIN + 1: # 保证新的货币有足够的时间计算均线 # 计算双均线 short_avgs = hitory_data.rolling(window=SHORT_WIN).mean() long_avgs = hitory_data.rolling(window=LONG_WIN).mean() # 双均线策略 # 短期均线上穿长期均线 if (short_avgs[-2] < long_avgs[-2]) and (short_avgs[-1] >= long_avgs[-1]): # 形成金叉 context.up_cross_signaled.add(asset) # 短期均线下穿长期均线 if (short_avgs[-2] > long_avgs[-2]) and (short_avgs[-1] <= long_avgs[-1]): # 形成死叉 context.down_cross_signaled.add(asset) # 卖出均线死叉信号的持仓交易对 for asset in context.portfolio.positions: if asset in context.down_cross_signaled: order_target(asset, 0) # 买入均线金叉信号的持仓股 for asset in context.up_cross_signaled: if asset not in context.portfolio.positions: close_price = data.current(asset, 'close') available_cash = get_available_cash(context) if available_cash > 0: # 如果有可用现金 # 每个交易对平均分配现金 cash_for_each_asset = available_cash / len(context.available_asset_pool) amount_to_buy = cash_for_each_asset / close_price # 计算购买的数量 if amount_to_buy >= asset.min_trade_size: # 购买的数量大于最小购买数量 order(asset, amount_to_buy) # 持仓比例 pos_level = context.portfolio.positions_value / context.portfolio.portfolio_value # 记录每个交易周期的现金 record(cash=context.portfolio.cash, pos_level=pos_level) # 输出信息 log.info('日期:{},资产:{:.2f},持仓比例:{:.6f}%,持仓产品:{}'.format( data.current_dt, context.portfolio.portfolio_value, pos_level * 100, ', '.join([asset.asset_name for asset in context.portfolio.positions])) )
def handle_data(context, data): log.info('=== handling bar {}'.format(data.current_dt)) order(context.asset, 1) record(btc=data.current(context.asset, 'price'))
def default_handle_data(context, data): context.curr_minute = data.current_dt context.counter += 1 if context.candles_sample_rate == 1: context.i += 1 elif context.counter % context.candles_sample_rate != 0: context.i += 1 return if context.i < context.parameters.SKIP_FIRST_CANDLES: return context.candles_open = data.history( context.coin_pair, 'open', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) context.candles_high = data.history( context.coin_pair, 'high', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) context.candles_low = data.history( context.coin_pair, 'low', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) context.candles_close = data.history( context.coin_pair, 'price', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) context.candles_volume = data.history( context.coin_pair, 'volume', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) # FIXME: Here is the error! # The candles_close frame shows more or less always a value of 94, while # bitcoin price is very different from that print(context.candles_close) context.base_prices = context.candles_close cash = context.portfolio.cash amount = context.portfolio.positions[context.coin_pair].amount price = data.current(context.coin_pair, 'price') order_id = None context.last_base_price = context.base_prices[-2] context.curr_base_price = context.base_prices[-1] # TA calculations # ... # Sanity checks # assert cash >= 0 if cash < 0: import ipdb; ipdb.set_trace() # BREAKPOINT print_facts(context) print_facts_telegram(context) # Order management net_shares = 0 if context.counter == 2: brute_shares = (cash / price) * context.parameters.BUY_PERCENTAGE share_commission_fee = brute_shares * context.parameters.COMMISSION_FEE net_shares = brute_shares - share_commission_fee buy_order_id = order(context.coin_pair, net_shares) if context.counter == 3: brute_shares = amount * context.parameters.SELL_PERCENTAGE share_commission_fee = brute_shares * context.parameters.COMMISSION_FEE net_shares = -(brute_shares - share_commission_fee) sell_order_id = order(context.coin_pair, net_shares) # Record record( price=price, foo='bar', # volume=current['volume'], # price_change=price_change, # Metrics cash=cash, # buy=context.buy, # sell=context.sell )
def handle_data(context, data): log.info('=== handling bar {}'.format(data.current_dt)) for b in context.assets: log.info(f'=== b: {b.symbol}') order(b, 1)
def handle_data(context, data): order(context.asset, 1)
def handle_data1(context, data): context.i += 1 lookback_days = 10 # 7 days # current date & time in each iteration formatted into a string now = data.current_dt date, time = now.strftime('%Y-%m-%d %H:%M:%S').split(' ') lookback_date = now - timedelta(days=lookback_days) # keep only the date as a string, discard the time lookback_date = lookback_date.strftime('%Y-%m-%d %H:%M:%S').split(' ')[0] one_day_in_minutes = 1440 # 60 * 24 assumes data_frequency='minute' # update universe everyday at midnight if not context.i % one_day_in_minutes: context.universe = universe(context, lookback_date, date) # get data every 30 minutes minutes = 120 # get lookback_days of history data: that is 'lookback' number of bins lookback = int(one_day_in_minutes / minutes * lookback_days) if not context.i % minutes and context.universe: # we iterate for every pair in the current universe for coin in context.coins: pair = str(coin.symbol) if pair == 'btc_usd': context.coin = coin # Get 30 minute interval OHLCV data. This is the standard data # required for candlestick or indicators/signals. Return Pandas # DataFrames. 30T means 30-minute re-sampling of one minute data. # Adjust it to your desired time interval as needed. opened = fill( data.history(coin, 'open', bar_count=lookback, frequency='2H')).values # import ipdb;ipdb.set_trace() high = fill( data.history(coin, 'high', bar_count=lookback, frequency='2H')).values low = fill( data.history(coin, 'low', bar_count=lookback, frequency='2H')).values close = fill( data.history(coin, 'price', bar_count=lookback, frequency='2H')).values volume = fill( data.history(coin, 'volume', bar_count=lookback, frequency='2H')).values # close[-1] is the last value in the set, which is the equivalent # to current price (as in the most recent value) # displays the minute price for each pair every 30 minutes print('{now}: {pair} -\tO:{o},\tH:{h},\tL:{c},\tC{c},' '\tV:{v}'.format( now=now, pair=pair, o=opened[-1], h=high[-1], l=low[-1], c=close[-1], v=volume[-1], )) current = lookback enter_fast = current - 55 exit_fast = current - 20 enter_slow = current - 32 exit_slow = current - 16 fastL = max(high[enter_fast:current - 1]) fastLC = min(low[exit_fast:current - 1]) fastS = min(low[enter_fast:current - 1]) fastSC = max(high[exit_fast:current - 1]) slowL = max(high[enter_slow:current - 1]) slowLC = min(low[exit_slow:current - 1]) slowS = min(low[enter_slow:current - 1]) slowSC = max(high[exit_slow:current - 1]) # cal 波幅 tech = talib.ATR(high, low, close, 20) # 买入点和卖出点 # TODO: Try to add risk limits! enterL1 = high[-1] > fastL exitL1 = low[-1] <= fastLC enterS1 = low[-1] < fastS exitS1 = high[-1] >= fastSC enterL2 = high[-1] > slowL exitL2 = low[-1] <= slowLC enterS2 = low[-1] < slowS exitS2 = high[-1] >= slowSC # Since we are using limit orders, some orders may not execute immediately # we wait until all orders are executed before considering more trades. orders = context.blotter.open_orders if len(orders) > 0: return position = context.portfolio.positions[coin].amount print(enterL1, context.openTriggers) global earn pnl_thistime = 0 if context.closeFlag['fastL'] == True: pnl = context.portfolio.pnl #global earn pnl_thistime = pnl - sum(earn['fastL']) earn['fastL'].append(pnl_thistime) context.closeFlag['fastL'] = False if context.closeFlag['fastS'] == True: pnl = context.portfolio.pnl #global earn pnl_thistime = pnl - sum(earn['fastS']) earn['fastS'].append(pnl_thistime) context.closeFlag['fastS'] = False # strategy.entry("fast L", strategy.long, when = (enterL1 and (time > timestamp(FromYear, FromMonth, FromDay, 00, 00)) and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) # strategy.entry("fast L", strategy.long, when = (enterL1 and (time > timestamp(FromYear, FromMonth, FromDay, 00, 00)) and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) if position and len( context.openPrices['fastL']) and context.openPrices[ 'fastL'][-1] - close[-1] > 2 * tech[-1]: print('stop loss for long') order_target_percent(coin, 0) context.openTriggers['fastL'] = 0 context.openPrices['fastL'] = [] context.closeFlag['fastL'] = True # pnl_last=context.portfolio.pnl if position and len( context.openPrices['fastS']) and context.openPrices[ 'fastS'][-1] - close[-1] < -2 * tech[-1]: print('stop loss for short') order_target_percent(coin, 0) context.openTriggers['fastS'] = 0 context.openPrices['fastS'] = [] context.closeFlag['fastS'] = True # strategy.close("fast L", when = (exitL1 and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) # Check holdings, if long, then flatten, otherwise, do nothing if exitL1 and context.openTriggers['fastL'] != 0: print("Close Long") order_target_percent(coin, 0) context.openTriggers['fastL'] = 0 context.openPrices['fastL'] = [] context.closeFlag['fastL'] = True # strategy.close("fast S", when = (exitS1 and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) # Check holdings, if short, then flatten, otherwise, do nothing if exitS1 and context.openTriggers['fastS'] != 0: print("Close Short") order_target_percent(coin, 0) context.openTriggers['fastS'] = 0 context.openPrices['fastS'] = [] context.closeFlag['fastS'] = True if context.openTriggers['fastL'] < 4 and len( context.openPrices['fastS']) == 0: if len(context.openPrices['fastL'] ) and close[-1] > context.openPrices['fastL'][-1]: print('Reloading Long') fastL = context.openPrices['fastL'][-1] + tech[-1] * 0.5 # import ipdb;ipdb.set_trace() pos_amount = context.portfolio.portfolio_value volume = pos_amount * 0.01 / tech[-1] orderid = order(coin, amount=volume) #order_target_percent(coin, 0.01) context.openTriggers['fastL'] += 1 print("fastL", context.openTriggers['fastL']) context.openPrices['fastL'].append(fastL) elif enterL1 and len(context.openPrices['fastL']) == 0: # import ipdb;ipdb.set_trace() context.openPrices['fastL'].append(fastL) fastL = fastL + tech[-1] * 0.5 pos_amount = context.portfolio.portfolio_value volume = pos_amount * 0.01 / tech[-1] orderid = order(coin, amount=volume) #order_target_percent(coin, 0.01) context.openTriggers['fastL'] += 1 print("fastL", context.openTriggers['fastL']) context.openPrices['fastL'].append(fastL) # strategy.entry("fast S", strategy.short, when = (enterS1 and (time > timestamp(FromYear, FromMonth, FromDay, 00, 00)) and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) if context.openTriggers['fastS'] < 4 and len( context.openPrices['fastL']) == 0: if len(context.openPrices['fastS'] ) and close[-1] < context.openPrices['fastS'][-1]: print("reloading short") fastS = context.openPrices['fastS'][-1] - tech[-1] * 0.5 pos_amount = context.portfolio.portfolio_value volume = pos_amount * 0.01 / tech[-1] orderid = order(coin, amount=-volume) #order_target_percent(coin, 0.01) context.openTriggers['fastS'] += 1 context.openPrices['fastS'].append(fastS) elif enterS1 and len(context.openPrices['fastS']) == 0: # import ipdb;ipdb.set_trace() print('open short') context.openPrices['fastS'].append(fastS) fastS = fastS - tech[-1] * 0.5 pos_amount = context.portfolio.portfolio_value volume = pos_amount * 0.01 / tech[-1] orderid = order(coin, amount=-volume) #order_target_percent(coin, 0.01) context.openTriggers['fastS'] += 1 context.openPrices['fastS'].append(fastS) ''' # strategy.entry("slow L", strategy.long, when = (enterL2 and (time > timestamp(FromYear, FromMonth, FromDay, 00, 00)) and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) if enterL2 and not context.openTriggers['slowL']: print("Open slow Long") order_target_percent(coin, 0.05) context.openTriggers['slowL'] = True # strategy.entry("slow S", strategy.short, when = (enterS2 and (time > timestamp(FromYear, FromMonth, FromDay, 00, 00)) and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) if enterS2 and not context.openTriggers['slowS']: print("Open slow Short") order_target_percent(coin, -0.05) context.openTriggers['slowS'] = True # strategy.close("slow L", when = (exitL2 and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) if exitL2 and position > 0 and context.openTriggers['slowL']: print("Close slow Long") order_target_percent(coin, 0) context.openTriggers['slowL'] = False # strategy.close("slow S", when = (exitS2 and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59)))) if exitS2 and position < 0 and context.openTriggers['slowS']: print("Close slow Short") order_target_percent(coin, 0) context.openTriggers['slowS'] = False ''' # // zl=0 # // z=strategy.netprofit / 37 * koef //ежемесячная прибыль # // z=strategy.grossprofit/strategy.grossloss # // z1=plot (z, style=line, linewidth=3, color = z>zl?green:red, transp = 30) # // hline(zl, title="Zero", linewidth=1, color=gray, linestyle=dashed) # // plot(strategy.equity) # Let's keep the price of our asset in a more handy variable price = data.current(coin, 'price') # If base_price is not set, we use the current value. This is the # price at the first bar which we reference to calculate price_change. if context.base_price is None: context.base_price = price price_change = (price - context.base_price) / context.base_price record(price=price, cash=context.portfolio.cash, price_change=price_change, fastL=fastL, fastLC=fastLC, fastS=fastS, fastSC=fastSC, slowL=slowL, lowLC=slowLC, slowS=slowS, slowSC=slowSC, pnl=pnl_thistime)
def default_handle_data(context, data): context.curr_minute = data.current_dt context.counter += 1 if context.candles_sample_rate == 1: context.i += 1 elif context.counter % context.candles_sample_rate != 0: context.i += 1 return if context.i < context.parameters.SKIP_FIRST_CANDLES: return context.candles_open = data.history(context.coin_pair, 'open', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) context.candles_high = data.history(context.coin_pair, 'high', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) context.candles_low = data.history(context.coin_pair, 'low', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) context.candles_close = data.history(context.coin_pair, 'price', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) context.candles_volume = data.history( context.coin_pair, 'volume', bar_count=context.candles_buffer_size, frequency=context.candles_frequency) # FIXME: Here is the error! # The candles_close frame shows more or less always a value of 94, while # bitcoin price is very different from that print(context.candles_close) context.base_prices = context.candles_close cash = context.portfolio.cash amount = context.portfolio.positions[context.coin_pair].amount price = data.current(context.coin_pair, 'price') # order_id = None context.last_base_price = context.base_prices[-2] context.curr_base_price = context.base_prices[-1] # TA calculations # ... # Sanity checks # assert cash >= 0 if cash < 0: import ipdb ipdb.set_trace() # BREAKPOINT print_facts(context) print_facts_telegram(context) # Order management # net_shares = 0 if context.counter == 2: pass brute_shares = (cash / price) * context.parameters.BUY_PERCENTAGE share_commission_fee = brute_shares * context.parameters.COMMISSION_FEE net_shares = brute_shares - share_commission_fee buy_order_id = order(context.coin_pair, net_shares) print(buy_order_id) if context.counter == 3: pass brute_shares = amount * context.parameters.SELL_PERCENTAGE share_commission_fee = brute_shares * context.parameters.COMMISSION_FEE net_shares = -(brute_shares - share_commission_fee) sell_order_id = order(context.coin_pair, net_shares) print(sell_order_id) # Record record( price=price, foo='bar', # volume=current['volume'], # price_change=price_change, # Metrics cash=cash, # buy=context.buy, # sell=context.sell )
def handle_data(context, data): order(context.asset, 1) record(btc=data.current(context.asset, 'price'))
def handle_data(context, data): order(context.assets[0], 1) prices = data.current(context.assets, 'price') record(price=prices) pass
def _handle_data(context, data): price = data.current(context.asset, 'price') log.info('got price {price}'.format(price=price)) prices = data.history( context.asset, fields='price', bar_count=20, frequency='1D' ) rsi = talib.RSI(prices.values, timeperiod=14)[-1] log.info('got rsi: {}'.format(rsi)) # Buying more when RSI is low, this should lower our cost basis if rsi <= 30: buy_increment = 1 elif rsi <= 40: buy_increment = 0.5 elif rsi <= 70: buy_increment = 0.2 else: buy_increment = 0.1 cash = context.portfolio.cash log.info('base currency available: {cash}'.format(cash=cash)) record( price=price, rsi=rsi, ) orders = context.blotter.open_orders if orders: log.info('skipping bar until all open orders execute') return is_buy = False cost_basis = None if context.asset in context.portfolio.positions: position = context.portfolio.positions[context.asset] cost_basis = position.cost_basis log.info( 'found {amount} positions with cost basis {cost_basis}'.format( amount=position.amount, cost_basis=cost_basis ) ) if position.amount >= context.TARGET_POSITIONS: log.info('reached positions target: {}'.format(position.amount)) return if price < cost_basis: is_buy = True elif (position.amount > 0 and price > cost_basis * (1 + context.PROFIT_TARGET)): profit = (price * position.amount) - (cost_basis * position.amount) log.info('closing position, taking profit: {}'.format(profit)) order_target_percent( asset=context.asset, target=0, limit_price=price * (1 - context.SLIPPAGE_ALLOWED), ) else: log.info('no buy or sell opportunity found') else: is_buy = True if is_buy: if buy_increment is None: log.info('the rsi is too high to consider buying {}'.format(rsi)) return if price * buy_increment > cash: log.info('not enough base currency to consider buying') return log.info( 'buying position cheaper than cost basis {} < {}'.format( price, cost_basis ) ) order( asset=context.asset, amount=buy_increment, limit_price=price * (1 + context.SLIPPAGE_ALLOWED) )
def handle_data(context, data): poloniex_price = data.current(context.poloniex_trading_pair, 'price') bitfinex_price = data.current(context.bitfinex_trading_pair, 'price') slippage = 0.03 sell_p, buy_p = get_adjusted_prices(poloniex_price, slippage) sell_b, buy_b = get_adjusted_prices(bitfinex_price, slippage) sell_r, buy_r = get_adjusted_prices(bit trex_price, slippage) #Buy Poloniex, Sell Bitfinex #Buy Bitfinex, Sell Poloniex #Buy Bitfinex, Sell Bittrex if is_profitable_after_fees(sell_r, buy_b, context.bittrex, context.bitfinex): print('Date:{}'.format(data.current_dt)) print('Bitfinex Price:{}, Bittrex Price: {}'.format(bitfinex_price, bittrex_price)) order(asset=context.bitfinex_trading_pair, amount=1, limit_price= buy_b) order(asset=context.bittrex_trading_pair, amount=1, limit_price= sell_r) #Buy Bittrex, Sell Bitfinex elif is_profitable_after_fees(sell_b, buy_r, context.bitfinex, context.bittrex): print('Date: {}'.format(data.current_dt)) print('Bittrex Price: {}, Bitfinex Price: {}'.format(bittrex_price, bitfinex_price)) order(asset=context.bittrex_trading_pair, amount=1, limit_price= buy_r) order(asset=context.bitfinex_trading_pair, amount=1, limit_price=sell_b) #Buy Bitfinex, Sell Poloniex elif is_profitable_after_fees(sell_p, buy_b, context.poloniex, context.bitfinex): print('Date: {}'.format(data.current_dt)) print('Bitfinex Price: {}, Poloniex Price: {}'.format(bitfinex_price, poloniex_price)) order(asset=context.bitfinex_trading_pair, amount=1, limit_price=buy_b) order(asset=context.poloniex_trading_pair, amount=-1, limit_price=sell_p) #Buy Poloniex, Sell Bitfinex elif is_profitable_after_fees(sell_b, buy_p, context.bitfinex, context.poloniex): print('Date: {}'.format(data.current_dt)) print('Bitfinex Price: {}, Poloniex Price: {}'.format(bitfinex_price, poloniex_price)) order(asset=context.poloniex_trading_pair, amount=1, limit_price=buy_p) order(asset=context.bitfinex_trading_pair, amount=-1, limit_price=sell_b)
def _handle_data(context, data): price = data.current(context.asset, 'close') log.info('got price {price}'.format(price=price)) if price is None: log.warn('no pricing data') return prices = data.history(context.asset, fields='price', bar_count=1, frequency='1m') rsi = talib.RSI(prices.values, timeperiod=14)[-1] log.info('got rsi: {}'.format(rsi)) # Buying more when RSI is low, this should lower our cost basis if rsi <= 30: buy_increment = 1 elif rsi <= 40: buy_increment = 0.5 elif rsi <= 70: buy_increment = 0.1 else: buy_increment = None cash = context.portfolio.cash log.info('base currency available: {cash}'.format(cash=cash)) record(price=price) orders = get_open_orders(context.asset) if len(orders) > 0: log.info('skipping bar until all open orders execute') return is_buy = False cost_basis = None if context.asset in context.portfolio.positions: position = context.portfolio.positions[context.asset] cost_basis = position.cost_basis log.info( 'found {amount} positions with cost basis {cost_basis}'.format( amount=position.amount, cost_basis=cost_basis)) if position.amount >= context.TARGET_POSITIONS: log.info('reached positions target: {}'.format(position.amount)) return if price < cost_basis: is_buy = True elif position.amount > 0 and \ price > cost_basis * (1 + context.PROFIT_TARGET): profit = (price * position.amount) - (cost_basis * position.amount) log.info('closing position, taking profit: {}'.format(profit)) order_target_percent( asset=context.asset, target=0, limit_price=price * (1 - context.SLIPPAGE_ALLOWED), ) else: log.info('no buy or sell opportunity found') else: is_buy = True if is_buy: if buy_increment is None: return if price * buy_increment > cash: log.info('not enough base currency to consider buying') return log.info('buying position cheaper than cost basis {} < {}'.format( price, cost_basis)) limit_price = price * (1 + context.SLIPPAGE_ALLOWED) order(asset=context.asset, amount=buy_increment, limit_price=limit_price) pass
def place_orders(context, amount, buying_price, selling_price, action): """ This method will always place two orders of the same amount to keep the currency position the same as it moves between the two exchanges. :param context: TradingAlgorithm :param amount: float The trading pair amount to trade on both exchanges. :param buying_price: float The current trading pair price on the buying exchange. :param selling_price: float The current trading pair price on the selling exchange. :param action: string "enter": buys on the buying exchange and sells on the selling exchange "exit": buys on the selling exchange and sells on the buying exchange :return: """ if action == 'enter': enter_exchange = context.buying_exchange entry_price = buying_price exit_exchange = context.selling_exchange exit_price = selling_price elif action == 'exit': enter_exchange = context.selling_exchange entry_price = selling_price exit_exchange = context.buying_exchange exit_price = buying_price else: raise ValueError('invalid order action') quote_currency = enter_exchange.quote_currency quote_currency_amount = enter_exchange.portfolio.cash exit_balances = exit_exchange.get_balances() exit_currency = context.trading_pairs[ context.selling_exchange].quote_currency if exit_currency in exit_balances: quote_currency_amount = exit_balances[exit_currency] else: log.warn( 'the selling exchange {exchange_name} does not hold ' 'currency {currency}'.format( exchange_name=exit_exchange.name, currency=exit_currency ) ) return if quote_currency_amount < (amount * entry_price): adj_amount = quote_currency_amount / entry_price log.warn( 'not enough {quote_currency} ({quote_currency_amount}) to buy ' '{amount}, adjusting the amount to {adj_amount}'.format( quote_currency=quote_currency, quote_currency_amount=quote_currency_amount, amount=amount, adj_amount=adj_amount ) ) amount = adj_amount elif quote_currency_amount < amount: log.warn( 'not enough {currency} ({currency_amount}) to sell ' '{amount}, aborting'.format( currency=exit_currency, currency_amount=quote_currency_amount, amount=amount ) ) return adj_buy_price = entry_price * (1 + context.SLIPPAGE_ALLOWED) log.info( 'buying {amount} {trading_pair} on {exchange_name} with price ' 'limit {limit_price}'.format( amount=amount, trading_pair=context.trading_pair_symbol, exchange_name=enter_exchange.name, limit_price=adj_buy_price ) ) order( asset=context.trading_pairs[enter_exchange], amount=amount, limit_price=adj_buy_price ) adj_sell_price = exit_price * (1 - context.SLIPPAGE_ALLOWED) log.info( 'selling {amount} {trading_pair} on {exchange_name} with price ' 'limit {limit_price}'.format( amount=-amount, trading_pair=context.trading_pair_symbol, exchange_name=exit_exchange.name, limit_price=adj_sell_price ) ) order( asset=context.trading_pairs[exit_exchange], amount=-amount, limit_price=adj_sell_price ) pass
def handle_data(context, data): order(context.asset, 1) record(btc=data.current(context.asset, 'price'))
def place_orders(context, amount, buying_price, selling_price, action): """ This method will always place two orders of the same amount to keep the currency position the same as it moves between the two exchanges. :param context: TradingAlgorithm :param amount: float The trading pair amount to trade on both exchanges. :param buying_price: float The current trading pair price on the buying exchange. :param selling_price: float The current trading pair price on the selling exchange. :param action: string "enter": buys on the buying exchange and sells on the selling exchange "exit": buys on the selling exchange and sells on the buying exchange :return: """ if action == 'enter': enter_exchange = context.buying_exchange entry_price = buying_price exit_exchange = context.selling_exchange exit_price = selling_price elif action == 'exit': enter_exchange = context.selling_exchange entry_price = selling_price exit_exchange = context.buying_exchange exit_price = buying_price else: raise ValueError('invalid order action') quote_currency = enter_exchange.quote_currency quote_currency_amount = enter_exchange.portfolio.cash exit_balances = exit_exchange.get_balances() exit_currency = context.trading_pairs[ context.selling_exchange].quote_currency if exit_currency in exit_balances: quote_currency_amount = exit_balances[exit_currency] else: log.warn('the selling exchange {exchange_name} does not hold ' 'currency {currency}'.format(exchange_name=exit_exchange.name, currency=exit_currency)) return if quote_currency_amount < (amount * entry_price): adj_amount = quote_currency_amount / entry_price log.warn( 'not enough {quote_currency} ({quote_currency_amount}) to buy ' '{amount}, adjusting the amount to {adj_amount}'.format( quote_currency=quote_currency, quote_currency_amount=quote_currency_amount, amount=amount, adj_amount=adj_amount)) amount = adj_amount elif quote_currency_amount < amount: log.warn('not enough {currency} ({currency_amount}) to sell ' '{amount}, aborting'.format( currency=exit_currency, currency_amount=quote_currency_amount, amount=amount)) return adj_buy_price = entry_price * (1 + context.SLIPPAGE_ALLOWED) log.info('buying {amount} {trading_pair} on {exchange_name} with price ' 'limit {limit_price}'.format( amount=amount, trading_pair=context.trading_pair_symbol, exchange_name=enter_exchange.name, limit_price=adj_buy_price)) order(asset=context.trading_pairs[enter_exchange], amount=amount, limit_price=adj_buy_price) adj_sell_price = exit_price * (1 - context.SLIPPAGE_ALLOWED) log.info('selling {amount} {trading_pair} on {exchange_name} with price ' 'limit {limit_price}'.format( amount=-amount, trading_pair=context.trading_pair_symbol, exchange_name=exit_exchange.name, limit_price=adj_sell_price)) order(asset=context.trading_pairs[exit_exchange], amount=-amount, limit_price=adj_sell_price) pass
def handle_data(context, data): print("I am in handle_data") order(context.asset, 1) record(btc=data.current(context.asset, 'price'))