def buy_back_shorted(ticker: str, trader: shift.Trader): item = trader.get_portfolio_item(ticker) while(item.get_shares() < 0): orders_placed = place_orders(shift.Order.Type.MARKET_BUY,ticker, int(-1* item.get_shares() / 100)) sleep(10) item = trader.get_portfolio_item(ticker) print(f'submitted buy for {ticker}')
def sell_long(ticker: str, trader: shift.Trader): item = trader.get_portfolio_item(ticker) while(item.get_shares() > 0): orders_placed = place_orders(shift.Order.Type.MARKET_SELL,ticker, int(item.get_shares() / 100)) sleep(10) item = trader.get_portfolio_item(ticker) # sell = shift.Order(shift.Order.Type.MARKET_SELL,ticker, int(item.get_shares() / 100)) # Order size in 100's of shares, strictly as an int # trader.submit_order(sell) print(f'submitted sell for {ticker}')
def closePositions(trader: shift.Trader, ticker): # Cancel pending orders print("Waiting list size:", trader.get_waiting_list_size()) for order in trader.get_waiting_list(): if order.symbol == ticker: trader.submit_cancellation(order) print("All", ticker, "pending orders cancelled" ) # Cancel open orders before submitting closing orders # Close / Cover all open positions #portfolioSummary(trader) # Print summary of portfolio**************************************************************************Good for developing item = trader.get_portfolio_item(ticker) if item.get_shares() > 0: closeLong = shift.Order( shift.Order.Type.MARKET_SELL, item.get_symbol(), int(item.get_shares() / 100)) # Order size in 100's of shares, strictly as an int trader.submit_order(closeLong) #print("Close all long positions") elif item.get_shares() < 0: coverShort = shift.Order(shift.Order.Type.MARKET_BUY, item.get_symbol(), int(item.get_shares() / -100)) trader.submit_order(coverShort) #print("Close all short positions") print("All", ticker, "closing orders submitted") return
def run_mm_long(ticker: str, trader: shift.Trader, end_time): minimum_spread = 0.02 maximum_allocation = 0.15 while trader.get_last_trade_time() < end_time: sleep(frequency) item = trader.get_portfolio_item(ticker) shares = item.get_shares() ask,bid,mid = get_prices(ticker) if bid == 0 or ask == 0: continue spread = (ask-bid) portfolio_value_of_ticker = shares*mid allocation = maximum_allocation*1000000 if allocation > portfolio_value_of_ticker: lots = 3 price = bid if spread < minimum_spread: price -= 0.01 order = place_limit_order(shift.Order.Type.LIMIT_BUY, ticker, lots, price) status = get_order_status(order) check_order(order, trader) else: continue
def run_mm_short(ticker: str, trader: shift.Trader, end_time): minimum_spread = 0.02 maximum_allocation = 0.1 while trader.get_last_trade_time() < end_time: sleep(frequency) item = trader.get_portfolio_item(ticker) short_shares = item.get_short_shares() ask,bid,mid = get_prices(ticker) if int(ask) == 0 or int(bid) == 0: continue spread = (ask-bid) portfolio_value_of_ticker = (short_shares*mid) allocation = maximum_allocation*1000000 if allocation > portfolio_value_of_ticker: lots = 3 price=ask if spread < minimum_spread: price += 0.01 order = place_limit_order(shift.Order.Type.LIMIT_SELL, ticker, lots, price) check_order(order, trader) else: continue
def buy_back_half(ticker: str, trader: shift.Trader): item = trader.get_portfolio_item(ticker) if item.get_shares() == -100: orders_placed = place_orders(shift.Order.Type.MARKET_BUY,ticker, int(-1* item.get_shares() / 100)) else: orders_placed = place_orders(shift.Order.Type.MARKET_BUY,ticker, int((-1* item.get_shares() / 100)/2)) sleep(10) print(f'submitted buy for {ticker}')
def get_unrealized_pl(ticker: str, trader: shift.Trader): p = trader.get_last_price(ticker) item = trader.get_portfolio_item(ticker) upl = -1 if item.get_shares() < 0 else 1 currValue = item.get_shares() * p cost = item.get_shares() * item.get_price() if cost == 0: return 0 upl = upl*((currValue - cost)/cost) return upl
def manage_inventory(ticker: str, trader: shift.Trader, end_time): while trader.get_last_trade_time() < end_time: sleep(frequency) upl = get_unrealized_pl(ticker, trader) item = trader.get_portfolio_item(ticker) if int(item.get_price()) != 0: if upl >= 0.4 or upl <= -0.2: print(f"Closing positions on {ticker} for {'loss' if upl <= -0.2 else 'profit'}") if item.get_shares() > 0: sell_long(ticker) elif item.get_shares() < 0: buy_back_shorted(ticker)
def check_pnl(ticker: str, trader: shift.Trader, state: Dict[str, Any], end_time): while trader.get_last_trade_time() < end_time: bid = trader.get_best_price(ticker).get_bid_price() ask = trader.get_best_price(ticker).get_ask_price() mid_price = (bid + ask) / 2 shares = trader.get_portfolio_item(ticker).get_shares() cost = trader.get_portfolio_item(ticker).get_price() unrealized_pnl = 0 if shares < 0: unrealized_pnl = (-1 * shares * cost) - (-1 * shares * mid_price) elif shares > 0: unrealized_pnl = (shares * mid_price) - (shares * cost) print(f"Current Mid Price: {mid_price}") print(f"Current Time P&L: {unrealized_pnl}") if unrealized_pnl >= 500: if trader.get_portfolio_item(ticker).get_shares() > 0: sell_half(ticker, trader) print("SELLING HALF LONGS FOR PROFIT") else: buy_back_half(ticker, trader) print("BUYING BACK HALF SHORTS FOR PROFIT") elif unrealized_pnl <= -500: if trader.get_portfolio_item(ticker).get_shares() > 0: sell_half(ticker, trader) print("SELLING HALF LONGS FOR LOSS") else: buy_back_half(ticker, trader) print("BUYING BACK HALF SHORTS FOR LOSS") sleep(candle_size / 2)
def longer(trader: shift.Trader, tickers): today = trader.get_last_trade_time() endTime = dt.time(15, 50, 0) dayEnd = dt.datetime.combine(today, endTime) tickSize = 0.01 bp = (trader.get_portfolio_summary().get_total_bp()) dpa = bp / float(len(tickers)) for t in tickers: lastPrice = trader.get_last_price(t) while lastPrice == 0: lastPrice = trader.get_last_price(t) s = int((dpa / lastPrice) / 100) for i in range(0, s): # limitBuyPrice = lastPrice - tickSize limit_sell = shift.Order(shift.Order.Type.MARKET_BUY, t, 1) trader.submit_order(limit_sell) while trader.get_last_trade_time() < dayEnd: time.sleep(1) for order in trader.get_waiting_list(): trader.submit_cancellation(order) for t in tickers: print(t) lastPrice = trader.get_last_price(t) item = trader.get_portfolio_item(t) if item.get_shares() > 0: sell = shift.Order( shift.Order.Type.MARKET_SELL, t, int(item.get_shares() / 100)) # Order size in 100's of shares, strictly as an int trader.submit_order(sell) elif item.get_shares() < 0: buy = shift.Order( shift.Order.Type.MARKET_BUY, t, int(-1 * item.get_shares() / 100)) # Order size in 100's of shares, strictly as an int trader.submit_order(buy) print(f'submitted buy for {t}') time.sleep(15) utils.print_portfolio_information(trader) utils.print_all_submitted_order(trader) print(trader.get_last_trade_time()) return
def run_trades(trader: shift.Trader, state: Dict[str, Any]) -> None: """ run buy / sell trades """ run_trades_interval = 60 # seconds while True: sleep(run_trades_interval) unsorted_differences: List[float] = [] unsorted_tickers: List[str] = [] for ticker in tickers: prices = np.array(list(state[prices_key][ticker])) ema_difference, price_minus_bollinger = get_should_long(prices) unsorted_differences.append(ema_difference) unsorted_tickers.append(ticker) _, ranked_tickers = map( list, zip(*sorted(zip(unsorted_differences, unsorted_tickers)))) for ticker in ranked_tickers: prices = np.array(list(state[prices_key][ticker])) ema_difference, price_minus_bollinger = get_should_long(prices) item = trader.get_portfolio_item(ticker) if item.get_shares() > 0: # check to sell if price_minus_bollinger > 0 or ema_difference < 0: sell = shift.Order( shift.Order.Type.MARKET_SELL, ticker, int(math.ceil((item.get_shares() / 2) / 100.0))) trader.submit_order(sell) else: for order in trader.get_waiting_list(): if order.symbol == ticker and order.type == shift.Order.Type.MARKET_BUY: trader.submit_cancellation(order) if ema_difference > 0: bp = trader.get_portfolio_summary().get_total_bp() amount = 200e3 if bp >= amount: lastPrice = trader.get_last_price(ticker) s = int((amount / lastPrice) / 100.) buy = shift.Order(shift.Order.Type.MARKET_BUY, ticker, s) trader.submit_order(buy)
def get_unrealized_pl(ticker: str, trader: shift.Trader): p = trader.get_last_price(ticker) item = trader.get_portfolio_item(ticker) long_shares = item.get_long_shares() short_shares = item.get_short_shares() upl = 0 curr_long_value = long_shares * p cost_long = long_shares * item.get_long_price() curr_short_value = short_shares * p cost_short = short_shares * item.get_short_price() if cost_long != 0: upl += (curr_long_value - cost_long)/float(cost_long) if cost_short != 0: upl -= (curr_short_value - cost_short)/float(cost_short) return upl
def run_trades(trader: shift.Trader, state: Dict[str, Any]) -> None: """ run buy / sell trades """ run_trades_interval = 60 # seconds maxLoss = 0.01 while True: # if (len()) unsorted_differences: List[float] = [] unsorted_tickers: List[str] = [] for ticker in tickers: print(f"entered run trades: {ticker}") if (ticker not in state[prices_key]) or len(list(state[prices_key][ticker])) < 22: # print(f"have {len(list(state[prices_key][ticker]))} prices for {ticker}...moving on") continue prices = np.array(list(state[prices_key][ticker])) # print(f"Prices({len(prices)}): {prices} ") should_long = get_should_long(prices) if(should_long is None): # print(f"should_long is None {ticker}") continue ema_difference = should_long["ema_difference"] prev_ema_difference = should_long["prev_ema_difference"] # print(f"emaaaaa {ticker}: {ema_difference}") unsorted_differences.append(ema_difference) unsorted_tickers.append(ticker) if(len(unsorted_differences) < 5): sleep(5) continue print(unsorted_differences) print(unsorted_tickers) _, ranked_tickers = (reversed(list(t)) for t in zip(*sorted(zip(unsorted_differences, unsorted_tickers)))) for ticker in ranked_tickers: prices = np.array(list(state[prices_key][ticker])) should_long = get_should_long(prices) if(should_long is None): sleep(1) continue ema_difference = should_long["ema_difference"] price_minus_bollinger_high = should_long["bollinger_band_high_difference"] price_minus_bollinger_low = should_long["bollinger_band_low_difference"] last_upper_bollinger_band = should_long["last_bollinger_band_high"] last_lower_bollinger_band = should_long["last_bollinger_band_low"] item = trader.get_portfolio_item(ticker) if item.get_shares() > 0: # check to sell target_hit_count = state[target_key][ticker][0] if ema_difference < 0: cancel_all_trades(trader, ticker) sleep(2) print(f"{ticker} : HAVE SHARES, EMA CROSSED DOWN, SELL") sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, int(item.get_shares()/100.0)) trader.submit_order(sell) # over band, never hit elif price_minus_bollinger_high > 0 and target_hit_count == 0: cancel_all_trades(trader, ticker) sleep(2) s = item.get_shares() print(f"{ticker} : HAVE SHARES, FIRST TARGET HIT, SELL HALF") sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, int(math.ceil((s/2) / 100.0))) trader.submit_order(sell) sleep(5) #check if you didn't happen to sell all due to minimum lot if int(math.ceil((item.get_shares()/2) / 100.0)) < int(s/100): lastPrice = trader.get_last_price(ticker) initial_buy_price = item.get_price() #keep track of this in state trailing_stop_perc = (lastPrice - initial_buy_price) / initial_buy_price trailing_stop_price = (1 - trailing_stop_perc) * lastPrice print(f"{ticker} : HAVE SHARES, FIRST TARGET HIT, RESETTING LIMIT SELL") sell = shift.Order(shift.Order.Type.LIMIT_SELL, ticker, int(math.ceil((item.get_shares()/2) / 100.0)), trailing_stop_price) trader.submit_order(sell) state[target_key][ticker] = [target_hit_count + 1, trailing_stop_perc] elif target_hit_count > 0: sold = 0 if price_minus_bollinger_low > 0: cancel_all_trades(trader, ticker) sleep(2) sold = int(math.ceil((item.get_shares()/2) / 100.0)) print(f"{ticker} : HAVE SHARES, OVER FIRST TARGET HIT, TAKING MORE PROFIT SINCE STILL ABOVE BOLLINGER, SELL HALFT") sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, sold) trader.submit_order(sell) sleep(5) if sold < int(item.get_shares()/100): lastPrice = trader.get_last_price(ticker) avg_last_two_prices = (state[prices_key][ticker][-2] + state[prices_key][ticker][-1]) / 2. if lastPrice >= avg_last_two_prices: cancel_all_trades(trader, ticker) sleep(2) # keep same percentarange and update the loss PRICE trailing_stop_perc = state[target_key][ticker][1] trailing_stop_price = (1 - trailing_stop_perc) * lastPrice print(f"{ticker} : HAVE SHARES, OVER FIRST TARGET HIT, SOLD MORE PROFIT SINCE STILL ABOVE BOLLINGER, STILL HAVE MORE, RESETTING LIMIT") sell = shift.Order(shift.Order.Type.LIMIT_SELL, ticker, item.get_shares() / 100.0, trailing_stop_price) trader.submit_order(sell) sleep(5) else: pass elif item.get_shares() < 0: #check to see if we need to exit short positions target_hit_count = state[target_key][ticker][0] if ema_difference > 0: cancel_all_trades(trader, ticker) sleep(2) buy = Shift.Order(shift.Order.Type.MARKET_BUY, ticker, -1*int(item.get_shares()/100.0)) trader.submit_order(buy) elif price_minus_bollinger_low < 0 and target_hit_count == 0: cancel_all_trades(trader, ticker) sleep(2) s = item.get_shares() buy = shift.Order(shift.Order.Type.MARKET_BUY, ticker, -1*int(math.ceil((s/2) / 100.0))) trader.submit_order(buy) sleep(5) #check if you happen to buy all back due to minimum lot #if still have short positions, reset limit buy if -1*int(math.ceil((item.get_shares()/2) / 100.0)) < -1*int(s/100) : lastPrice = trader.get_last_price(ticker) initial_sell_price = item.get_price() trailing_stop_perc = (lastPrice - initial_sell_price) / initial_sell_price trailing_stop_price = (1 + trailing_stop_perc) * lastPrice buy = shift.Order(shift.Order.Type.LIMIT_BUY, ticker, int(math.ceil((item.get_shares()/2) / 100.0)), trailing_stop_price) trader.submit_order(buy) state[target_key][ticker] = [target_hit_count + 1, trailing_stop_perc] #no close of position at all, so we just wanna reset the trailing stop loss elif target_hit_count > 0: bought = 0 if price_minus_bollinger_low < 0: cancel_all_trades(trader, ticker) sleep(2) bought = -1*int(math.ceil((item.get_shares()/2) / 100.0)) buy = shift.Order(shift.Order.Type.MARKET_BUY, ticker, bought) trader.submit_order(buy) sleep(5) if bought < -1*int(item.get_shares() / 100.0): lastPrice = trader.get_last_price(ticker) avg_last_two_prices = (state[prices_key][ticker][-2] + state[prices_key][ticker][-1]) / 2. # keep same percentarange and update the loss PRICE #TODO: fix a dollar amount instead of percentage if lastPrice <= avg_last_two_prices: cancel_all_trades(trader, ticker) sleep(2) trailing_stop_perc = state[target_key][1] trailing_stop_price = (1 + trailing_stop_perc) * lastPrice buy = shift.Order(shift.Order.Type.LIMIT_BUY, ticker, item.get_shares() / 100.0, trailing_stop_price) trader.submit_order(buy) else: pass else: #reset target_hit_count because no shores no more state[target_key][ticker] = [0,0] for order in trader.get_waiting_list(): if order.symbol == ticker and order.type == shift.Order.Type.MARKET_BUY: trader.submit_cancellation(order) sleep(2) if ema_difference > 0 and prev_ema_difference < 0: bp = trader.get_portfolio_summary().get_total_bp() amount = 200e3 if bp >= amount: lastPrice = trader.get_last_price(ticker) s = int((amount / lastPrice) / 100.) buy = shift.Order(shift.Order.Type.MARKET_BUY, ticker, s) initial_buy_price = trader.get_last_price(ticker) initial_stop_loss = shift.Order(shift.Order.Type.LIMIT_SELL, ticker, s, trader.get_last_price(ticker)*(1-maxLoss)) print(f"{ticker} : DONT HAVE SHARES, HIT TARGET, HAVE BP, BUY") trader.submit_order(buy) sleep(5) print(f"{ticker} : DONT HAVE SHARES, HIT TARGET, HAVE BP, SETTING INITIAL STOP LOSS") trader.submit_order(initial_stop_loss) elif ema_difference < 0: bp = trader.get_portfolio_summary().get_total_bp() short_profit, long_profit = get_unrealized_pl(trader) #lost money on shorts amount = (200e3 / 2) amount_to_subtract = 0 if short_profit < 0: amount_to_subtract += (-1*short_profit) if (0.995 * (amount - amount_to_subtract)) < bp: lastPrice = trader.get_last_price() s = int((amount / lastPrice) / 100.) sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, s) initial_sell_price = trader.get_last_price(ticker) initial_stop_loss = shift.Order(shift.Order.Type.LIMIT_BUY, ticker, trader.get_last_price(ticker)*(1+maxLoss), s) trader.submit_order(sell) sleep(5) trader.submit_order(initial_stop_loss) sleep(5) sleep(run_trades_interval)
def marketMaker(trader: shift.Trader, ticker, dayEnd, allocation, orderType, lag=3, fillTime=30, spreadWiden=0.00): # Datetime of simulation rightNow = trader.get_last_trade_time() fillTime = fillTime * 10 # While the time is before end of day... while dayEnd > rightNow: time.sleep(lag) # Give prices some time to change """ Make Trades Here: """ onHand = trader.get_portfolio_item(ticker).get_shares() * ( (trader.get_best_price(ticker).get_bid_price() + trader.get_best_price(ticker).get_ask_price()) / 2 ) # Portfolio value of the stock maxAllowed = allocation * ( 1000000 + trader.get_portfolio_summary().get_total_realized_pl() ) # Maximum portfolio allocation for this stock print(ticker, "on hand:", round(onHand, 2), "max:", round(maxAllowed), " P/L:", round(trader.get_portfolio_summary().get_total_realized_pl(), 2), " Waiting list:", trader.get_waiting_list_size()) if onHand > maxAllowed and orderType == shift.Order.Type.LIMIT_BUY: # Holding too much continue # Allow Sell side to catch up elif onHand < -maxAllowed and orderType == shift.Order.Type.LIMIT_SELL: # Short too much continue # Allow Buy side to catch up time.sleep(lag) # Give prices some time to change # Submit an order bid = trader.get_best_price(ticker).get_bid_price() ask = trader.get_best_price(ticker).get_ask_price() spreadWiden = max(.01, (ask - bid) * .25) if (ask - bid) < .05: # If spread is too tight, widen it spreadWiden = -spreadWiden if orderType == shift.Order.Type.LIMIT_BUY: size = max( 1, round(trader.get_best_price(ticker).get_ask_size() / 5) ) # Only buy as much as you can sell. Divide by 5 so buying power lasts on high volume. At least 1 price = bid + spreadWiden # Can buy above bid if wide spread, or below bid if high volume elif orderType == shift.Order.Type.LIMIT_SELL: size = max( 1, round(trader.get_best_price(ticker).get_ask_size() / 5) ) # Only sell as much as you can buy back. Divide by 5 to decrease risk. At least 1 price = ask - spreadWiden # Can sell below ask if wide spread, or above ask if high volume order = shift.Order(orderType, ticker, size, price) trader.submit_order(order) #print(orderType, size, ticker, "@", price) # Give the order time to fill waitCount = 1 while trader.get_order( order.id ).status != shift.Order.Status.FILLED and waitCount <= fillTime and trader.get_order( order.id).status != shift.Order.Status.REJECTED: #print(waitCount, ticker, "Status:",trader.get_order(order.id).status) time.sleep(.1) waitCount = waitCount + 1 #print(waitCount, trader.get_order(order.id).status) # Cancel the buy order if never filled and was not rejected if trader.get_order( order.id ).status != shift.Order.Status.REJECTED and trader.get_order( order.id).status != shift.Order.Status.FILLED: trader.submit_cancellation(order) #print("Cancelled", ticker) rightNow = trader.get_last_trade_time() # Reset datetime of right now # 30 minutes till end of trading day closePositions(trader, ticker) # Done trading return
def manageInventory(trader: shift.Trader, ticker, dayEnd): # Datetime of simulation rightNow = trader.get_last_trade_time() # While the time is before end of day... while (dayEnd > rightNow): time.sleep(5) # Give prices time to fluctuate item = trader.get_portfolio_item(ticker) if item.get_shares() != 0: unrealizedPL = 0 tradedPrice = item.get_price() numShares = int( item.get_shares() / 100) # Order size in 100's of shares, strictly as an int if numShares > 0: unrealizedPL = ( (trader.get_close_price(ticker, False, numShares) - tradedPrice) / tradedPrice) * 100 else: # numShares < 0: unrealizedPL = -( (trader.get_close_price(ticker, True, -numShares) - tradedPrice) / tradedPrice) * 100 print(ticker, "Unrealized P/L:", unrealizedPL, "%") if unrealizedPL >= 0.40: # Target met, take profit #if unrealizedPL >= 3.0: # Target met, take profit if item.get_shares() > 0: closePositions(trader, ticker) """ closeLong = shift.Order(shift.Order.Type.MARKET_SELL, item.get_symbol(), numShares) trader.submit_order(closeLong) """ print(ticker, "take profit on long") time.sleep( 5 ) # Don't act on volatile spikes and dips, only identify longer trends elif item.get_shares() < 0: closePositions(trader, ticker) """ coverShort = shift.Order(shift.Order.Type.MARKET_BUY, item.get_symbol(), -numShares) trader.submit_order(coverShort) """ print(ticker, "take profit on short") time.sleep( 5 ) # Don't act on volatile spikes and dips, only identify longer trends elif unrealizedPL <= -0.30: # Stop loss met, sell risk #elif unrealizedPL <= -0.50: # Stop loss met, sell risk if item.get_shares() > 0: closePositions(trader, ticker) """ closeLong = shift.Order(shift.Order.Type.MARKET_SELL, item.get_symbol(), numShares) trader.submit_order(closeLong) """ print(ticker, "stop loss on long") time.sleep( 5 ) # Don't act on volatile spikes and dips, only identify longer trends elif item.get_shares() < 0: closePositions(trader, ticker) """ coverShort = shift.Order(shift.Order.Type.MARKET_BUY, item.get_symbol(), -numShares) trader.submit_order(coverShort) """ print(ticker, "stop loss on short") time.sleep( 5 ) # Don't act on volatile spikes and dips, only identify longer trends rightNow = trader.get_last_trade_time() # Reset datetime of right now
def run_trades(trader: shift.Trader, state: Dict[str, Any]) -> None: """ run buy / sell trades """ run_trades_interval = 30 # seconds maxLoss = 0.004 maxGain = 0.004 while True: unsorted_differences: List[float] = [] unsorted_tickers: List[str] = [] for ticker in tickers: if (ticker not in state[prices_key]) or len( list(state[prices_key][ticker])) < 21: sleep(5) continue prices = np.array(list(state[prices_key][ticker])) should_long = get_should_long(prices) ema_difference = should_long["ema_difference"] unsorted_differences.append(ema_difference) unsorted_tickers.append(ticker) if ticker == "AAPL": print("PRE UNPACKING") print(unsorted_differences) print(unsorted_tickers) print((list(t) for t in zip( *sorted(zip(unsorted_differences, unsorted_tickers))))) _, ranked_tickers = (list(t) for t in zip( *sorted(zip(unsorted_differences, unsorted_tickers)))) for ticker in ranked_tickers: prices = np.array(list(state[prices_key][ticker])) should_long = get_should_long(prices) ema_difference = should_long["ema_difference"] price_minus_bollinger_high = should_long[ "bollinger_band_high_difference"] price_minus_bollinger_low = should_long[ "bollinger_band_low_difference"] last_upper_bollinger_band = should_long["last_bollinger_band_high"] last_lower_bollinger_band = should_long["last_bollinger_band_low"] item = trader.get_portfolio_item(ticker) if item.get_shares() > 0: # check to sell target_hit_count = state[target_key][ticker][0] if ema_difference < 0: cancel_all_trades(trader, ticker) sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, int(item.get_shares() / 100.0)) trader.submit_order(sell) elif price_minus_bollinger_high > 0 and target_hit_count == 0: # over band, never hit cancel_all_trades(trader, ticker) s = item.get_shares() sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, int(math.ceil((s / 2) / 100.0))) trader.submit_order(sell) #check if you happen to sell all due to minimum lot #if still have long positions, reset limit sell if int(math.ceil( (item.get_shares() / 2) / 100.0)) < int(s / 100): lastPrice = trader.get_last_price(ticker) initial_buy_price = item.get_price() trailing_stop_perc = ( lastPrice - initial_buy_price) / initial_buy_price trailing_stop_price = (1 - trailing_stop_perc) * lastPrice sell = shift.Order( shift.Order.Type.LIMIT_SELL, ticker, int(math.ceil((item.get_shares() / 2) / 100.0)), trailing_stop_price) trader.submit_order(sell) #keep track of this in state state[target_key][ticker] = [ target_hit_count + 1, trailing_stop_perc ] elif target_hit_count > 0: sold = 0 if price_minus_bollinger_high > 0: cancel_all_trades(trader, ticker) sold = int(math.ceil((item.get_shares() / 2) / 100.0)) sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, sold) trader.submit_order(sell) if sold < int(item.get_shares() / 100): lastPrice = trader.get_last_price(ticker) avg_last_two_prices = ( state[prices_key][ticker][-2] + state[prices_key][ticker][-1]) / 2. #we have shares, hits target for 2nd time, and price > upper bo, and we took 1/2 profit, we still have more if lastPrice >= avg_last_two_prices: cancel_all_trades(trader, ticker) # keep same percentarange and update the loss PRICE #TODO: fix a dollar amount instead of percentage trailing_stop_perc = state[target_key][ticker][1] trailing_stop_price = ( 1 - trailing_stop_perc) * lastPrice sell = shift.Order(shift.Order.Type.LIMIT_SELL, ticker, item.get_shares() / 100.0, trailing_stop_price) trader.submit_order(sell) else: pass #comment this if you want to yeet the short logic elif item.get_shares() < 0: #check to see if we need to exit short positions target_hit_count = state[target_key][ticker][0] if ema_difference > 0: cancel_all_trades(trader, ticker) buy = Shift.Order(shift.Order.Type.MARKET_BUY, ticker, -1 * int(item.get_shares() / 100.0)) trader.submit_order(buy) elif price_minus_bollinger_low < 0 and target_hit_count == 0: cancel_all_trades(trader, ticker) s = item.get_shares() buy = shift.Order(shift.Order.Type.MARKET_BUY, ticker, -1 * int(math.ceil((s / 2) / 100.0))) trader.submit_order(buy) #check if you happen to buy all back due to minimum lot #if still have short positions, reset limit buy if -1 * int(math.ceil( (item.get_shares() / 2) / 100.0)) < -1 * int(s / 100): lastPrice = trader.get_last_price(ticker) initial_sell_price = item.get_price() trailing_stop_perc = (lastPrice - initial_sell_price ) / initial_sell_price trailing_stop_price = (1 + trailing_stop_perc) * lastPrice buy = shift.Order( shift.Order.Type.LIMIT_BUY, ticker, int(math.ceil((item.get_shares() / 2) / 100.0)), trailing_stop_price) trader.submit_order(buy) state[target_key][ticker] = [ target_hit_count + 1, trailing_stop_perc ] #no close of position at all, so we just wanna reset the trailing stop loss elif target_hit_count > 0: bought = 0 if price_minus_bollinger_low < 0: cancel_all_trades(trader, ticker) bought = -1 * int( math.ceil((item.get_shares() / 2) / 100.0)) buy = shift.Order(shift.Order.Type.MARKET_BUY, ticker, bought) trader.submit_order(buy) if bought < -1 * int(item.get_shares() / 100.0): lastPrice = trader.get_last_price(ticker) avg_last_two_prices = ( state[prices_key][ticker][-2] + state[prices_key][ticker][-1]) / 2. # keep same percentarange and update the loss PRICE #TODO: fix a dollar amount instead of percentage if lastPrice <= avg_last_two_prices: cancel_all_trades(trader, ticker) trailing_stop_perc = state[target_key][1] trailing_stop_price = ( 1 + trailing_stop_perc) * lastPrice buy = shift.Order(shift.Order.Type.LIMIT_BUY, ticker, item.get_shares() / 100.0, trailing_stop_price) trader.submit_order(buy) else: pass else: #reset target_hit_count because no shares no more state[target_key][ticker] = [0, 0] for order in trader.get_waiting_list(): if order.symbol == ticker and order.type == shift.Order.Type.MARKET_BUY: trader.submit_cancellation(order) if order.symbol == ticker and order.type == shift.Order.Type.MARKET_SELL: trader.submit_cancellation(order) if ema_difference > 0: bp = trader.get_portfolio_summary().get_total_bp() amount = 200e3 if bp >= amount: lastPrice = trader.get_last_price(ticker) s = int((amount / lastPrice) / 100.) buy = shift.Order(shift.Order.Type.MARKET_BUY, ticker, s) initial_buy_price = trader.get_last_price(ticker) initial_stop_loss = shift.Order( shift.Order.Type.LIMIT_SELL, ticker, trader.get_last_price(ticker) * (1 - maxLoss), s) trader.submit_order(buy) trader.submit_order(initial_stop_loss) #comment this if you want to yeet the short logic elif ema_difference < 0: bp = trader.get_portfolio_summary().get_total_bp() short_profit, long_profit = get_unrealized_pl(trader) #lost money on shorts amount = (200e3 / 2) amount_to_subtract = 0 if short_profit < 0: amount_to_subtract += (-1 * short_profit) if (0.995 * (amount - amount_to_subtract)) < bp: lastPrice = trader.get_last_price() s = int((amount / lastPrice) / 100.) sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, s) initial_sell_price = trader.get_last_price(ticker) initial_stop_loss = shift.Order( shift.Order.Type.LIMIT_BUY, ticker, trader.get_last_price(ticker) * (1 + maxLoss), s) trader.submit_order(sell) trader.submit_order(initial_stop_loss) # # check to see if we should enter short position pass sleep(run_trades_interval)