def await_market_open(num): setup_folders() num += 1 if num > 4: print("market not opening today") return print("checking time...") client = build_client() today = datetime.date.today() try: clock = client.get_hours_for_single_market( market=client.Markets.EQUITY, date=today).json()["equity"]["EQ"] except: clock = client.get_hours_for_single_market( market=client.Markets.EQUITY, date=today).json()["equity"]["equity"] # app starts right at 9:30 est from scheduler # if it's a trading day, start the app if clock["isOpen"] == True: print("Beginning process.") scraper() # assess('skip') # time.sleep( 1 ) # This whole process (from scrape to starting watchdog) takes about 2-5 minutes daily_trader( 'initial' ) # so there's also inherently a delay between market open and when the app time.sleep(1) # starts trading run_watchdog(0) # else: print("market not open today.") sys.exit()
def kill_trade(symbol, qty, price, order_type): client = build_client() try: if order_type == "long": client.place_order(account_id=ACCOUNT_ID, order_spec=equity_sell_market(symbol, qty)) logging.info("Killed trade") record_trade(symbol, price) else: client.place_order(account_id=ACCOUNT_ID, order_spec=equity_buy_market(symbol, qty)) logging.info("Killed trade") record_trade(symbol, price) except: logging.info(f"Unexpected error killing trade: {sys.exc_info()}") pass
def run_watchdog(count): # poor man's web socket while count < 6500: count += 1 try: # for the first hour, rescan every 15 min # if count % 5 != 0 and count < 10: if count <= 900 and count % 225 == 0: rescan_stocks() # for the rest of the day, rescan every hour elif count > 900 and count % 900 == 0: rescan_stocks() # otherwise, run watchdog else: client = build_client() tCLT = threading.Thread(target=check_long_trades(client)) tCLT.start() tCST = threading.Thread(target=check_short_trades(client)) tCST.start() tCLT.join() tCST.join() tRL = threading.Thread(target=rate_limiter( count)) # this function has exit conditions tRL.start() tRL.join() except SystemExit: cancel_all('all') sys.exit() except KeyboardInterrupt: cancel_all('all') sys.exit() except: logging.info( "something went wrong running process, probably connection timeout." ) logging.info(f"Unexpected error: {sys.exc_info()}") pass
def start_test(count): cancel_all('all') client = build_client() if count < 1: count += 1 symbols = ['CRBP', 'QD', 'WPG', 'ANY'] for symbol in symbols: ph = client.get_price_history( symbol=symbol, period_type=client.PriceHistory.PeriodType.DAY, period=client.PriceHistory.Period.ONE_DAY, frequency_type=client.PriceHistory.FrequencyType.MINUTE, frequency=client.PriceHistory.Frequency.EVERY_FIFTEEN_MINUTES, start_datetime=None, end_datetime=None, need_extended_hours_data=None).json() print(ph['symbol']) df = pd.json_normalize(ph, 'candles') # pprint(len(df)) # pprint(df) # pprint(df['close']) # pprint(df['high']) # pprint(df['low']) # pprint(df['volume']) raw_vwap = VolumeWeightedAveragePrice(high=df['high'], low=df['low'], close=df['close'], volume=df['volume'], window=14) raw_ema = EMAIndicator(close=df['close'], window=9) print("vwap:") pprint(raw_vwap.vwap[len(raw_vwap.vwap) - 1]) print("ema:") pprint(raw_ema._close[len(raw_ema._close) - 1]) print("len ema:") print(len(raw_ema._close))
def daily_trader(str_): list_of_files = glob.glob("./csv's/trades/*.csv") sorted_files = sorted(list_of_files, key=os.path.getctime) most_recent_file = sorted_files[-1] # last file should be most recent one client = build_client() # cancel all open orders cancel_all('orders') print("Getting account balance...") account = client.get_account( account_id=ACCOUNT_ID).json()["securitiesAccount"] # print(f"account: {account}") # choose between account["currentBalances"][totalCash] for cash accounts, # or account["currentBalances"]["buyingPower"] for margin accounts if account["type"] == "CASH": # plan to use a cash account to avoid PDT rule, so need to spread the # trades over 3 days to allow cash to settle. Also, using this # number to automatically calculate qty of shares for each trade buying_power = account["currentBalances"]["totalCash"] if buying_power == 0.0: buying_power = account["currentBalances"][ "cashAvailableForTrading"] else: # later, when using a margin account, this becomes # a part of the risk management strategy buying_power = account["currentBalances"]["buyingPower"] daily_investment = round(float(buying_power) / 3, 2) print(daily_investment) # count rows with open(most_recent_file, newline='') as csvfile: reader = csv.DictReader(csvfile) print("Counting trades...") num_of_trades = len(list(reader)) csvfile.close() # create orders from most recent gap up analysis with open(most_recent_file, newline='') as csvfile: reader = csv.DictReader(csvfile) print("Creating orders...") try: investment_per_trade = round(daily_investment / num_of_trades, 2) # if number of trades == 0 except: investment_per_trade = 0.0 order_num = 0 error_num = 0 entries = 0 print(f"Num of trades is {num_of_trades}") print(f"inv per trade is {investment_per_trade}") for row in reader: entries += 1 symbol = row['Symbol'] last = float(row['Last']) quote = client.get_quote(symbol) bid = quote.json()[symbol]["bidPrice"] ask = quote.json()[symbol]["askPrice"] avg_price = round((bid + ask) / 2, 2) trade_check = check_for_trade(symbol) if trade_check: continue else: pass # if the price has moved down more than 15 cents, avg + 0.15 will be lower than last, and try to short the stock if avg_price + 0.15 < last: order_type = "short" entry_price = round(last - 0.10, 2) sl_price = str(round(entry_price * 1.07, 2)) # otherwise, price is stable or moving up, so make a long order else: order_type = "long" entry_price = round(last + 0.10, 2) sl_price = str(round(entry_price * 0.93, 2)) qty = int(round(investment_per_trade / entry_price, 0)) print(f"qty is {qty}") if entry_price == 0 or qty == 0: continue volume = row['Volume'] # to be used later gap_up_percent = row['Gap Up%'] # to be used later print( f"Symbol: {symbol} side: {order_type} target entry: {entry_price} Stop Loss price: {sl_price}" ) print(f"Symbol: {symbol} Vol: {volume} Gap Up% {gap_up_percent}") try: create_order(client, symbol, entry_price, qty, order_type) order_num += 1 except Exception as err: print(f"Error with {symbol}: {err}") error_num += 1 pass print(f"{entries} Entries found.") print(f"{order_num} Orders created.") print(f"{error_num} Errors encountered.") csvfile.close()
def cancel_all(str_): """ Pass 'all', 'trades', or 'orders' depending on what needs to be canceled. """ errors = [] client = build_client() # cancel all open orders if str_ == "all" or str_ == "orders": try: orders = client.get_orders_by_path(account_id=ACCOUNT_ID, max_results=None, from_entered_datetime=None, to_entered_datetime=None, status=client.Order.Status.QUEUED, statuses=None).json() print("Canceling orders...") # orders = orders.json() for order in orders: order_id = order["orderId"] print(f"Order ID: {order_id}") client.cancel_order(order_id=order_id, account_id=ACCOUNT_ID) print("Orders canceled.") except: print("Unexpected error canceling orders:", sys.exc_info()) errors.append(sys.exc_info()) pass # close all trades if str_ == "all" or str_ == "trades": try: account_with_positions = client.get_account(account_id=ACCOUNT_ID, fields=client.Account.Fields.POSITIONS).json()["securitiesAccount"] try: positions = account_with_positions["positions"] except: positions = {} print("Closing positions...") if positions == {}: print("No positions to close.") else: for trade in positions: print(positions) # submit sell order for the position symbol = trade["instrument"]["symbol"] short_quantity = trade["shortQuantity"] long_quantity = trade["longQuantity"] try: if long_quantity > 0: client.place_order( account_id=ACCOUNT_ID, order_spec=equities.equity_sell_market(symbol, long_quantity) ) # it might be a short position, so try a buy order elif short_quantity > 0: client.place_order( account_id=ACCOUNT_ID, order_spec=equities.equity_buy_market(symbol, short_quantity) ) else: print("No trades to close.") return except: print("Unexpected error closing trades:", sys.exc_info()) errors.append(sys.exc_info()) pass except: print("Unexpected error closing trades:", sys.exc_info()) errors.append(sys.exc_info()) pass if len(errors) > 0: print("errors with closing orders and positions:") print(errors) else: print("All orders canceled and positions closed.")
def assess(str): if str == "prompt": scrape_first = input("Scrape first, y/n? ") else: scrape_first = "n" if scrape_first == "y" or scrape_first == "Y" or scrape_first == "yes" or scrape_first == "Yes": scraper() time.sleep(10) else: pass # get 2 latest csv's from csv's directory list_of_files = glob.glob( "./csv's/raw/*.csv") # * means all if need specific format then *.csv sorted_files = sorted(list_of_files, key=os.path.getctime) recent_gap_down = sorted_files[ -1] # last file is gap downs, due to order in which they are scraped recent_gap_up = sorted_files[-2] # second to last will be gap ups gap_ups = [] gap_downs = [] client = build_client() account = client.get_account( account_id=ACCOUNT_ID).json()["securitiesAccount"] # choose between account["currentBalances"][totalCash] for cash accounts, # or account["currentBalances"]["buyingPower"] if account["type"] == "CASH": # plan to use a cash account to avoid PDT rule, so need to spread the # trades over 3 days to allow cash to settle. Also, using this # number to automatically calculate qty of shares for each trade buying_power = account["currentBalances"]["totalCash"] else: # later, when using a margin account, this becomes # a part of the risk management strategy buying_power = account["currentBalances"]["buyingPower"] if buying_power < 250: bottom_limit = 0.01 upper_limit = 10.0 else: bottom_limit = 1.0 upper_limit = 11.0 # analyze gap ups first # trade these, as they have something working favorably for them # which others will also bank on # looking for gap up over 4%, volume over 300k, and last daily closing price under $20 with open(recent_gap_up, newline='') as csvfile: stockreader = csv.DictReader(csvfile, delimiter=',', quotechar='"') print("===== Gap Ups: =====") for row in stockreader: try: # grab variables symbol = row['Symbol'] last = float(row['Last']) volume = int(float(row['Volume'].replace(",", ""))) gap_up_percent = float(row['Gap Up%'].replace("%", "")) # check for criteria above if volume >= 300000 and last >= bottom_limit and last <= upper_limit and gap_up_percent >= 4.0: print( f"{symbol}: Last - {last}, Gap Up% - {gap_up_percent}, Volume - {volume}" ) gap_ups.append([symbol, last, volume, gap_up_percent]) else: # don't fit criteria print(f"Skipped {symbol}: Outside parameters.") except: # quick fix for random rows in csv print("Error") continue csvfile.close() location = get_date_and_time("trades") with open(location, 'w', newline='') as csvfile: fieldnames = ['Symbol', 'Last', 'Volume', 'Gap Up%'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for stock in gap_ups: writer.writerow({ "Symbol": stock[0], "Last": stock[1], "Volume": stock[2], "Gap Up%": stock[3], }) csvfile.close() #anazlyze gap downs # looking for something that had a high price and has fallen due to recent news # add to a watchlist to profit off of recovery, or short the stock and profit off price drop with open(recent_gap_down, newline='') as csvfile: stockreader = csv.DictReader(csvfile, delimiter=',', quotechar='"') print("===== Gap Downs: =====") for row in stockreader: try: symbol = row['Symbol'] last = float(row['Last']) volume = int(float(row['Volume'].replace(",", ""))) gap_down_percent = float(row['Gap Down%'].replace("%", "")) if volume >= 300000 and last >= bottom_limit and last <= upper_limit and gap_down_percent < -4.5: print( f"{symbol}: Last - {last}, Gap Down% - {gap_down_percent}, Volume - {volume}" ) gap_downs.append([symbol, last, volume, gap_down_percent]) else: print(f"Skipped {symbol}: Outside parameters.") except: print("Error") continue csvfile.close() location = get_date_and_time("watches") with open(location, 'w', newline='') as csvfile: fieldnames = ['Symbol', 'Last', 'Volume', 'Gap Down%'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for stock in gap_downs: writer.writerow({ "Symbol": stock[0], "Last": stock[1], "Volume": stock[2], "Gap Down%": stock[3], }) csvfile.close()