def portfolioSummary(trader: shift.Trader): """Takes Trader Object and Prints Summary of Portfolio to Console""" print("Buying Power\tTotal Shares\tTotal P&L\tTimestamp") print("%12.2f\t%12d\t%9.2f\t%26s" % ( trader.get_portfolio_summary().get_total_bp(), trader.get_portfolio_summary().get_total_shares(), trader.get_portfolio_summary().get_total_realized_pl(), trader.get_portfolio_summary().get_timestamp(), )) print() print("Symbol\t\tShares\t\tPrice\t\t P&L\tTimestamp") for item in trader.get_portfolio_items().values(): print("%6s\t\t%6d\t%9.2f\t%9.2f\t%26s" % ( item.get_symbol(), item.get_shares(), item.get_price(), item.get_realized_pl(), item.get_timestamp(), )) print() return
def demo_07(trader: shift.Trader): """ This method provides information on the structure of PortfolioSummary and PortfolioItem objects: get_portfolio_summary() returns a PortfolioSummary object with the following data: 1. Total Buying Power (get_total_bp()) 2. Total Shares (get_total_shares()) 3. Total Realized Profit/Loss (get_total_realized_pl()) 4. Timestamp of Last Update (get_timestamp()) get_portfolio_items() returns a dictionary with "symbol" as keys and PortfolioItem as values, with each providing the following information: 1. Symbol (get_symbol()) 2. Shares (get_shares()) 3. Price (get_price()) 4. Realized Profit/Loss (get_realized_pl()) 5. Timestamp of Last Update (get_timestamp()) :param trader: :return: """ print("Buying Power\tTotal Shares\tTotal P&L\tTimestamp") print( "%12.2f\t%12d\t%9.2f\t%26s" % ( trader.get_portfolio_summary().get_total_bp(), trader.get_portfolio_summary().get_total_shares(), trader.get_portfolio_summary().get_total_realized_pl(), trader.get_portfolio_summary().get_timestamp(), ) ) print() print("Symbol\t\tShares\t\tPrice\t\t P&L\tTimestamp") for item in trader.get_portfolio_items().values(): print( "%6s\t\t%6d\t%9.2f\t%9.2f\t%26s" % ( item.get_symbol(), item.get_shares(), item.get_price(), item.get_realized_pl(), item.get_timestamp(), ) ) return
def demo_01(trader: shift.Trader): # We haven't developed a strategy yet. # We only want to test whether we could # get through the market/limit orders limit_buy = shift.Order(shift.Order.Type.LIMIT_BUY, "AAPL", 10, 165.00) trader.submit_order(limit_buy) xom_limit_buy = shift.Order(shift.Order.Type.LIMIT_BUY, "XOM", 10, 10.00) trader.submit_order(xom_limit_buy) aapl_market_buy = shift.Order(shift.Order.Type.MARKET_BUY, "AAPL", 1) trader.submit_order(aapl_market_buy) xom_market_buy = shift.Order(shift.Order.Type.MARKET_BUY, "XOM", 1) trader.submit_order(xom_market_buy) aapl_market_sell = shift.Order(shift.Order.Type.MARKET_SELL, "AAPL", 1) trader.submit_order(aapl_market_sell) xom_market_sell = shift.Order(shift.Order.Type.MARKET_SELL, "XOM", 1) trader.submit_order(xom_market_sell) print("AAPL:") print(" Price\t\tSize\t Dest\t\tTime") for order in trader.get_order_book("AAPL", shift.OrderBookType.LOCAL_BID): print("%7.2f\t\t%4d\t%6s\t\t%19s" % (order.price, order.size, order.destination, order.time)) print() print("XOM:") print(" Price\t\tSize\t Dest\t\tTime") for order in trader.get_order_book("XOM", shift.OrderBookType.LOCAL_BID): print("%7.2f\t\t%4d\t%6s\t\t%19s" % (order.price, order.size, order.destination, order.time)) print("Buying Power\tTotal Shares\tTotal P&L\tTimestamp") print("%12.2f\t%12d\t%9.2f\t%26s" % ( trader.get_portfolio_summary().get_total_bp(), trader.get_portfolio_summary().get_total_shares(), trader.get_portfolio_summary().get_total_realized_pl(), trader.get_portfolio_summary().get_timestamp(), )) return
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 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 technicalStrat(trader: shift.Trader, ticker, lastTradeSell, dayEnd, lag=1): rightNow = trader.get_last_trade_time() # Datetime of simulation # While the time is before end of day... while (dayEnd > rightNow): print("P/L:", trader.get_portfolio_summary().get_total_realized_pl(), " Waiting list:", trader.get_waiting_list_size()) """ Make Trades Here: """ priceSeries = pd.Series(trader.get_sample_prices( ticker, True)) # ticker, mid-prices time.sleep(lag) # Give prices some time to change if priceSeries.size == 26: mShort = priceSeries.ewm(span=12, adjust=False).mean() # 12 period EMA mLong = priceSeries.ewm(span=26, adjust=False).mean() # 26 period EMA MACD = mShort - mLong # Calculate convergence and divergence mSignal = MACD.ewm(span=9, adjust=False).mean() # 9 period EMA signal line mHist = MACD - mSignal # Trade signal producer SMA = priceSeries[:19].mean() # 20 second simple moving average if lastTradeSell == True: bUpper = SMA + (priceSeries[:19].std() * 3.0 ) # Upper Bollinger Band bLower = SMA - ( priceSeries[:19].std() * 1.5 ) # Low Bollinger Band - more lenient, safer sell else: bUpper = SMA + ( priceSeries[:19].std() * 1.5 ) # Upper Bollinger Band - more lenient, safer cover bLower = SMA - (priceSeries[:19].std() * 3.0 ) # Low Bollinger Band #######!!!!!!possibly have a second band outside first..for too strong movement!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Open long position / Cover short position if lastTradeSell == True and mHist.iloc[ -1] > 0 and trader.get_close_price( ticker, True, 1) > bUpper: # ticker, Buy, Size for i in range( 1, 20 ): # should scale based on order book amount in competition.. openLong = shift.Order(shift.Order.Type.MARKET_BUY, ticker, 1) trader.submit_order(openLong) print("Tech - Buy", ticker) lastTradeSell = False # Close long positions for now / Open short position elif lastTradeSell == False and mHist.iloc[ -1] < 0 and trader.get_close_price( ticker, False, 1) < bLower: # ticker, Sell, Size for i in range( 1, 20 ): # should scale based on order book amount in competition.. closeLong = shift.Order(shift.Order.Type.MARKET_SELL, ticker, 1) trader.submit_order(closeLong) print("Tech - Sell", ticker) lastTradeSell = True rightNow = trader.get_last_trade_time() # Reset datetime of right now # 60 seconds till end of trading day trader.cancel_all_sample_prices_requests( ) # Stop sampling prices on threads closePositions(trader, ticker) # Close out open positions so we don't get fined # 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)