def run_stop_loss_check(trader: shift.Trader, state: Dict[str, Any]) -> None: """ check for stop loss hit """ stop_loss_interval = 5 # seconds acceptable_loss = .2 # percent if stop_loss_key not in state: state[stop_loss_key] = {} while True: sleep(stop_loss_interval) for item in trader.get_portfolio_items().values(): ticker = item.get_symbol() current_price = state[prices_key][ticker][-1] new_stop_loss = current_price * ((100 - acceptable_loss) / 100.) has_stop_loss = ticker in state[stop_loss_key] if not has_stop_loss or new_stop_loss > state[stop_loss_key][ ticker]: if has_stop_loss: for order in trader.get_waiting_list(): if order.symbol == ticker and order.type == shift.Order.Type.LIMIT_SELL: trader.submit_cancellation(order) limit_sell = shift.Order(shift.Order.Type.LIMIT_SELL, ticker, item.get_shares()) trader.submit_order(limit_sell) state[stop_loss_key][ticker] = new_stop_loss, limit_sell
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 check_order(order, trader: shift.Trader): sleep(1) status = get_order_status(order) tries = 0 while status != shift.Order.Status.REJECTED and status != shift.Order.Status.FILLED and tries < 10: sleep(1) tries += 1 status = get_order_status(order) if status != shift.Order.Status.REJECTED and status != shift.Order.Status.FILLED: trader.submit_cancellation(order)
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 demo_05(trader: shift.Trader): """ This method cancels all the orders in the waiting list. :param trader: :return: """ print( "Symbol\t\t\t\tType\t Price\t\tSize\tExecuted\tID\t\t\t\t\t\t\t\t\t\t\t\t\t\t Status\t\tTimestamp" ) for o in trader.get_waiting_list(): print( "%6s\t%16s\t%7.2f\t\t%4d\t\t%4d\t%36s\t%23s\t\t%26s" % ( o.symbol, o.type, o.price, o.size, o.executed_size, o.id, o.status, o.timestamp, ) ) print() print("Waiting list size: " + str(trader.get_waiting_list_size())) print("Canceling all pending orders...", end=" ") # trader.cancel_all_pending_orders() also works for o in trader.get_waiting_list(): trader.submit_cancellation(o) i = 0 while trader.get_waiting_list_size() > 0: i += 1 print(i, end=" ") time.sleep(1) print() print("Waiting list size: " + str(trader.get_waiting_list_size())) return
def main(trader: shift.Trader) -> None: """ main entrypoint """ trader = shift.Trader(credentials.my_username) try: trader.connect("initiator.cfg", credentials.my_password) trader.sub_all_order_book() except shift.IncorrectPasswordError as e: print(e) except shift.ConnectionTimeoutError as e: print(e) time.sleep(2) check_time = 5 # minutes current = trader.get_last_trade_time() start_time = dt.combine(current, dt.datetime(10, 0, 0)) end_time = dt.combine(current, dt.datetime(15, 30, 0)) while trader.get_last_trade_time() < start_time: sleep(check_time * 60) processes = run_processes(trader) while trader.get_last_trade_time() < end_time: sleep(check_time * 60) for order in trader.get_waiting_list(): trader.submit_cancellation(order) for item in trader.get_portfolio_items().values(): ticker = item.get_symbol() sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, item.get_shares()) trader.submit_order(sell) time_wait_sell = 60 # seconds sleep(time_wait_sell) stop_processes(processes) # print stuff routine_summary(trader)
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 run_stop_loss_check(trader: shift.Trader, state: Dict[str, Any]) -> None: """ check for stop loss hit """ stop_loss_interval = 5 # seconds acceptable_loss = .2 # percent # if stop_loss_key not in stop_losses_state: # stop_losses_state = {} ''' Set original stop loss when originally buying to -.2% Set original target when originally buying to the bollinger band Update target every minute to the most recent bollinger band First time you hit target: remove half position update stop loss to original buy prices and make this a trailing stop Keep updating target Scenario: Buy 100 at 100 Set stop loss to 99.8 and target to 101 We hit 101 so we sell 50 (left with 50) and update stop loss to 100 101 - 100 = stop loss Next minute upper band changes to 102: change target to 102 Next minute upper band changes to 99: sell everything ALREADY HIT TARGET ONCE: We hit 102 so we sell 25 (left with 25) and update stop loss to 101 price goes to 101.50, stop loss is 101 price hits target at 104, stop loss is 103.50 begin position initial_buy_price = ... target = upper_bollinger_band[-1] stop_loss = initial_buy_price*-.002 first target hits stop_loss = (1 - ((first_target_sell - initial_buy_price) / initial_buy_price))*current_price price goes up stop_loss = (1 - ((first_target_sell - initial_buy_price) / initial_buy_price))*current_price second target hits - just half, and reapply trailing stop loss stop_loss = (1 - ((first_target_sell - initial_buy_price) / initial_buy_price))*current_price price goes down stop_loss = stop_loss ''' while True: sleep(stop_loss_interval) for item in trader.get_portfolio_items().values(): ticker = item.get_symbol() current_price = state[prices_key][ticker][-1] new_stop_loss = current_price * ((100 - acceptable_loss) / 100.) has_stop_loss = ticker in state[stop_loss_key] if not has_stop_loss or new_stop_loss > state[stop_loss_key][ticker]: if has_stop_loss: for order in trader.get_waiting_list(): if order.symbol == ticker and order.type == shift.Order.Type.LIMIT_SELL: trader.submit_cancellation(order) limit_sell = shift.Order(shift.Order.Type.LIMIT_SELL, ticker, item.get_shares()) trader.submit_order(limit_sell) state[stop_loss_key][ticker] = new_stop_loss, limit_sell
def main(trader: shift.Trader) -> None: """ main entrypoint """ # { # "prices": { # "AAPL": [234] # }, # } manager = Manager() list_of_shared_dicts = manager.list() list_of_shared_dicts.append({}) # prices_state = list_of_shared_dicts[0] # stop_losses_state = list_of_shared_dicts[1] state = list_of_shared_dicts[0] keys_in_state = [prices_key, stop_loss_key, target_key] for key in keys_in_state: state[key] = manager.dict() for ticker in tickers: if key == prices_key: state[key].setdefault(key, []) elif key == target_key: state[key].setdefault(key, [0,0]) # if key == stop_loss_key: # state[trader_key] = trader # trader_obj = state check_time = 1 # minutes current = trader.get_last_trade_time() start_time = datetime.combine(current, dt.time(10,0,0)) end_time = datetime.combine(current, dt.time(15, 30, 0)) print(trader.get_last_trade_time()) pre_processes = [] for ticker in tickers: # 1 thread per ticker getting price data & saving it pre_processes.append(Thread(target=run_save_prices, args=(ticker, trader, state))) # run_save_prices(ticker, trader, state) for process in pre_processes: process.start() print(f"{len(pre_processes)} processes created for run_save_prices") while trader.get_last_trade_time() < start_time: print(f"Waiting for Market Open @ {trader.get_last_trade_time()}") sleep(check_time * 60) processes = pre_processes.extend(run_processes(trader, state)) while trader.get_last_trade_time() < end_time: print(f"Waiting for Market Close @ {trader.get_last_trade_time()}") sleep(check_time * 60) for order in trader.get_waiting_list(): trader.submit_cancellation(order) for item in trader.get_portfolio_items().values(): ticker = item.get_symbol() sell = shift.Order(shift.Order.Type.MARKET_SELL, ticker, item.get_shares()) trader.submit_order(sell) time_wait_sell = 60 # seconds sleep(time_wait_sell) stop_processes(processes) # print stuff routine_summary(trader)
def cancel_all_trades(trader: shift.Trader, ticker: str): for o in trader.get_waiting_list(): if(o.symbol == ticker): trader.submit_cancellation(o)
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 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)