def triggeredUp(symbObj, curPrice, buyPrice, closePrice, maxPrice, sellUpDn, latestTrades): global gainers print("Starting thread for " + symbObj['symbol']) while ((curPrice / buyPrice >= maxPrice / buyPrice * sellUpDn or curPrice / closePrice >= maxPrice / closePrice * sellUpDn) and a.timeTillClose() >= 30): curPrice = a.getPrice(symbObj['symbol']) maxPrice = max(maxPrice, curPrice) print(symbObj['symbol'] + " - " + str(round(curPrice / buyPrice, 2)) + ":" + str(round(maxPrice / buyPrice * sellUpDn, 2)) + " - " + str(round(curPrice / closePrice, 2)) + ":" + str(round(maxPrice / closePrice, 2))) a.o.time.sleep(3) print(a.createOrder("sell", symbObj['qty'], symbObj['symbol'])) latestTrades[symbObj['symbol']] = { "tradeDate": str(a.o.dt.date.today()), "tradeType": "sell", "buyPrice": 0, #reset the avgBuyPrice to 0 after a sell "shouldSell": False } with open(a.o.c['latestTradesFile'], "w") as f: f.write(a.o.json.dumps(latestTrades, indent=2)) #remove from gainers in case it sells after updateStockList has run if (symbObj['symbol'] in gainers): gainers.remove(symbOjb['symbol'])
def check2buy(latestTrades, minBuyPow, buyPowMargin, minDolPerStock): usableBuyPow = float( a.getAcct()['buying_power']) #init as the current buying power if ( buyPowMargin < 1 ): #buyPowMargin MUST BE GREATER THAN 1 in order for it to work correctly raise ( "Error: withdrawlable funds margin is less than 1. Multiplier must be >=1" ) if ( usableBuyPow >= minBuyPow * buyPowMargin ): #if we have more buying power than the min plus some leeway, then reduce it to hold onto that buy pow print(f"Can safely withdrawl ${round(minBuyPow,2)}") usableBuyPow = usableBuyPow - minBuyPow * buyPowMargin #subtract the minBuyPow plus the margin elif (usableBuyPow > minBuyPow and usableBuyPow < minBuyPow * buyPowMargin): usableBuyPow = 0 #stop trading if we've started to eat into the margin, that way we don't overshoot if (len(gainers) > 0): dolPerStock = max( minDolPerStock, usableBuyPow / len(gainers) ) #if buyPow>(minDolPerStock*len(gainers)) then divvy up buyPow over gainers else: dolPerStock = minDolPerStock i = 0 #index of gainers stocksBought = 0 #number of stocks bought stocks2buy = int(usableBuyPow / dolPerStock) #number of stocks to buy while (stocksBought < stocks2buy and i < len(gainers)): symb = gainers[i] #candidate stock to buy #TODO: in this conditional, also check that the gain isn't greater than ~75% of sellUp (e.g. must be <1.15 if sellUp=1.2) if (symb not in [ t.getName() for t in threading.enumerate() ]): #make sure the stock isn't trying to be sold already try: #check when it was traded last lastTradeDate = a.o.dt.datetime.strptime( latestTrades[symb]['tradeDate'], '%Y-%m-%d').date() lastTradeType = latestTrades[symb]['tradeType'] try: avgBuyPrice = latestTrades[symb]['buyPrice'] except Exception: avgBuyPrice = 0 except Exception: lastTradeDate = a.o.dt.datetime.today().date( ) - a.o.dt.timedelta(1) lastTradeType = "NA" avgBuyPrice = 0 #for some reason this check was being bypassed. This should be resolved in the updateStockList function where it removes any prospective stock to be bought from the list if it was sold today if (lastTradeType != "sell" or lastTradeDate < a.o.dt.datetime.today().date() ): #make sure we didn't sell it today already if (a.isAlpacaTradable(symb) ): #make sure it's tradable on the market curPrice = a.getPrice(symb) if (curPrice > 0): shares2buy = int(dolPerStock / curPrice) orderText = a.createOrder("buy", shares2buy, symb, "market", "day") #make sure it actually executed the order, then increment if (orderText.endswith('accepted')): print(orderText) #record the transaction latestTrades[ symb] = { #set the avgBuyPrice to the average of the currentPrice and the previous avg (unless the prev avg<=0) "tradeDate": str(a.o.dt.date.today()), "tradeType": "buy", "buyPrice": (curPrice + avgBuyPrice) / (1 + avgBuyPrice > 0), "shouldSell": False } with open(a.o.c['latestTradesFile'], "w") as f: f.write(a.o.json.dumps(latestTrades, indent=2)) stocksBought += 1 i += 1 #try the next stock else: i += 1 #try the next stock else: i += 1 #try the next stock else: i += 1 #try the next stock else: i += 1 #try the next stock print("Done buying")
def check2sell(symList, latestTrades, mainSellDn, mainSellUp, sellUpDn): print( "symb\tinit jump\tpred jump (+/- 3wks)\tchg from buy\tchg from close\tsell points" ) print( "----\t---------\t--------------------\t------------\t--------------\t-----------" ) for e in symList: #if(a.isAlpacaTradable(e['symbol'])): #just skip it if it can't be traded - skipping this for slower connections & to save a query try: lastTradeDate = a.o.dt.datetime.strptime( latestTrades[e['symbol']]['tradeDate'], '%Y-%m-%d').date() lastTradeType = latestTrades[e['symbol']]['tradeType'] avgBuyPrice = float( e['avg_entry_price'] ) #if it doesn't exist, default to the avg buy price over all time - it's important to keep a separate record to reset after a sell rather than over all time except Exception: lastTradeDate = a.o.dt.date.today() - a.o.dt.timedelta(1) lastTradeType = "NA" avgBuyPrice = float(e['avg_entry_price']) try: shouldSell = latestTrades[e['symbol']]['shouldSell'] except Exception: #in the event it doesn't exist, don't worry about it shouldSell = False #if marked to sell, sell regardless of price immediately if (shouldSell): print(e['symbol'] + " marked for immediate sale.") print(a.createOrder("sell", e['qty'], e['symbol'])) latestTrades[e['symbol']] = { "tradeDate": str(a.o.dt.date.today()), "tradeType": "sell", "buyPrice": 0, "shouldSell": False } with open(a.o.c['latestTradesFile'], "w") as f: f.write(a.o.json.dumps(latestTrades, indent=2)) elif ( lastTradeDate < a.o.dt.date.today() or lastTradeType == "sell" or float(a.getPrice(e['symbol'])) / avgBuyPrice >= 1.75 ): #prevent selling on the same day as a buy (only sell if only other trade today was a sell or price increased substantially) buyPrice = avgBuyPrice closePrice = float(e['lastday_price']) #curPrice = float(e['current_price']) curPrice = a.getPrice(e['symbol']) maxPrice = 0 buyInfo = a.o.goodBuy(e['symbol'], 260) try: lastJump = a.o.dt.datetime.strptime(buyInfo, "%m/%d/%Y").date() #adjust selling targets based on date to add a time limit #sellUp change of 0 if <=5 weeks after initial jump, -.05 for every week after 6 weeks for a min of 1 sellUp = round( max( 1, mainSellUp - .05 * max( 0, int((a.o.dt.date.today() - (lastJump + a.o.dt.timedelta(6 * 7))).days / 7))), 2) #sellDn change of 0 if <=5 weeks after initial jump, +.05 for every week after 6 weeks for a max of 1 sellDn = round( min( 1, mainSellDn + .05 * max( 0, int((a.o.dt.date.today() - (lastJump + a.o.dt.timedelta(6 * 7))).days / 7))), 2) totalChange = round(curPrice / buyPrice, 2) dayChange = round(curPrice / closePrice, 2) print( f"{e['symbol']}\t{lastJump}\t{lastJump+a.o.dt.timedelta(5*7)}\t\t{bcolor.FAIL if totalChange<1 else bcolor.OKGREEN}{totalChange}{bcolor.ENDC}\t\t{bcolor.FAIL if dayChange<1 else bcolor.OKGREEN}{dayChange}{bcolor.ENDC}\t\t{sellUp} & {sellDn}" ) except Exception: print(e['symbol'] + " - " + buyInfo) sellUp = mainSellUp sellDn = mainSellDn #cut the losses if we missed the jump or if the price dropped too much if (buyPrice == 0 or curPrice / buyPrice <= sellDn or buyInfo == "Missed jump"): print("Lost it on " + e['symbol']) print(a.createOrder("sell", e['qty'], e['symbol'])) latestTrades[e['symbol']] = { "tradeDate": str(a.o.dt.date.today()), "tradeType": "sell", "buyPrice": 0, "shouldSell": False } with open(a.o.c['latestTradesFile'], "w") as f: f.write(a.o.json.dumps(latestTrades, indent=2)) #use e['lastday_price'] to get previous close amount ... or curPrice/float(e['lastday_price'])>=sellUpFromYesterday elif (curPrice / buyPrice >= sellUp or curPrice / closePrice >= sellUp): if ( not e['symbol'] in [t.getName() for t in threading.enumerate()] ): #if the thread is not found in names of the running threads, then start it (this stops multiple instances of the same stock thread) print("Trigger point reached on " + e['symbol'] + ". Seeing if it will go up...") triggerThread = threading.Thread( target=triggeredUp, args=(e, curPrice, buyPrice, closePrice, maxPrice, sellUpDn, latestTrades)) #init the thread triggerThread.setName( e['symbol']) #set the name to the stock symb triggerThread.start() #start the thread
def check2buyDJ(latestTrades, pos, minBuyPow, buyPowMargin, minDolPerStock): pQty = {e['symbol']: e['qty'] for e in pos} #isolate just the held stock and the # of shares usableBuyPow = float( a.getAcct()['cash']) #init as the current buying power if ( buyPowMargin < 1 ): #buyPowMargin MUST BE GREATER THAN 1 in order for it to work correctly raise ( "Error: withdrawlable funds margin is less than 1. Multiplier must be >=1" ) if ( usableBuyPow >= minBuyPow * buyPowMargin ): #if we have more buying power than the min plus some leeway, then reduce it to hold onto that buy pow print(f"Can safely withdrawl ${round(minBuyPow,2)}") usableBuyPow = usableBuyPow - minBuyPow * buyPowMargin #subtract the minBuyPow plus the margin elif (usableBuyPow > minBuyPow and usableBuyPow < minBuyPow * buyPowMargin): usableBuyPow = 0 #stop trading if we've started to eat into the margin, that way we don't overshoot if (len(gainers) > 0): #TODO: investigate this delaration? dolPerStock = max( minDolPerStock, usableBuyPow / len(gainers) ) #if buyPow>(minDolPerStock*len(gainers)) then divvy up buyPow over gainers else: dolPerStock = minDolPerStock i = 0 #index of gainers stocksBought = 0 #number of stocks bought stocks2buy = int(usableBuyPow / dolPerStock) #number of stocks to buy gainerList = list( gainers ) #Shuffle the list to avoid scanning from the top down every loop (must be a list rather than dict) random.shuffle(gainerList) while (stocksBought < stocks2buy and i < len(gainers)): symb = gainerList[i] #candidate stock to buy #TODO: in this conditional, also check that the gain isn't greater than ~75% of sellUp (e.g. must be <1.15 if sellUp=1.2) if ( symb not in [t.getName() for t in threading.enumerate()] and gainers[symb]['algo'] == "DJ" ): #make sure the stock isn't trying to be sold already and that the algorithm is doubleJump try: #check when it was traded last lastTradeDate = a.o.dt.datetime.strptime( latestTrades['doubleJump'][symb]['tradeDate'], '%Y-%m-%d').date() lastTradeType = latestTrades['doubleJump'][symb]['tradeType'] try: avgBuyPrice = latestTrades['doubleJump'][symb]['buyPrice'] except Exception: avgBuyPrice = 0 except Exception: lastTradeDate = a.o.dt.datetime.today().date( ) - a.o.dt.timedelta(1) lastTradeType = "NA" avgBuyPrice = 0 #for some reason this check was being bypassed. This should be resolved in the updateStockList function where it removes any prospective stock to be bought from the list if it was sold today if (lastTradeType != "sell" or lastTradeDate < a.o.dt.datetime.today().date() ): #make sure we didn't sell it today already # if(a.isAlpacaTradable(symb)): #make sure it's tradable on the market (optional check?) [curPrice, mktCap] = a.getPrice( symb, True ) #market cap is needed because we don't want to buy too much of the company that the pattern would no longer hold sharesHeld = 0 if (symb not in pQty) else float( pQty[symb] ) #get the shares held of a certain stock (if we have it) if (curPrice > 0): #calc outstanding shares, reduce to our acceptable holding % of shares, account for currently held shares (don't let it go negative). If within that range, then just look at the divvied cash shares2buy = min( max( int(mktCap / curPrice * float(a.o.c['Buy Params']['maxVolPerc']) - sharesHeld), 0), int(dolPerStock / curPrice)) #shares2buy = int(dolPerStock/curPrice) #outdated # of shares to buy (does not account for marketCap) orderText = a.createOrder("buy", shares2buy, symb, "market", "day") #make sure it actually executed the order, then increment if (orderText.endswith('accepted')): print(orderText) #record the transaction latestTrades['doubleJump'][ symb] = { #set the avgBuyPrice to the average of the currentPrice and the previous avg (unless the prev avg<=0) "tradeDate": str(a.o.dt.date.today()), "tradeType": "buy", "buyPrice": (curPrice + avgBuyPrice) / (1 + avgBuyPrice > 0), "shouldSell": False } with open(a.o.c['File Locations']['latestTradesFile'], "w") as f: f.write(a.o.json.dumps(latestTrades, indent=2)) stocksBought += 1 i += 1 #try the next stock else: i += 1 #try the next stock # else: # i += 1 #try the next stock else: i += 1 #try the next stock else: i += 1 #try the next stock print("Done buying")
def check2sellDJ(symList, latestTrades, mainSellDn, mainSellUp, sellUpDn): global jumpDates print( "symb\tchg from buy\tchg from close\tsell points\tinit jump\tpred jump (+/- 3wks)" ) print( "----\t------------\t--------------\t-----------\t---------\t--------------------" ) for e in symList: #if(a.isAlpacaTradable(e['symbol'])): #just skip it if it can't be traded - skipping this for slower connections & to save a query try: lastTradeDate = a.o.dt.datetime.strptime( latestTrades['doubleJump'][e['symbol']]['tradeDate'], '%Y-%m-%d').date() lastTradeType = latestTrades['doubleJump'][ e['symbol']]['tradeType'] avgBuyPrice = float( e['avg_entry_price'] ) #if it doesn't exist, default to the avg buy price over all time - it's important to keep a separate record to reset after a sell rather than over all time except Exception: lastTradeDate = a.o.dt.date.today() - a.o.dt.timedelta(1) lastTradeType = "NA" avgBuyPrice = float(e['avg_entry_price']) try: shouldSell = latestTrades['doubleJump'][e['symbol']]['shouldSell'] except Exception: #in the event it doesn't exist, don't worry about it shouldSell = False #if marked to sell, sell regardless of price immediately if (shouldSell): print(e['symbol'] + " marked for immediate sale.") print(a.createOrder("sell", e['qty'], e['symbol'])) latestTrades['doubleJump'][e['symbol']] = { "tradeDate": str(a.o.dt.date.today()), "tradeType": "sell", "buyPrice": 0, "shouldSell": False #TODO: add isTradable:date #TODO: add sharesHeld:## } with open(a.o.c['File Locations']['latestTradesFile'], "w") as f: f.write(a.o.json.dumps(latestTrades, indent=2)) elif ( lastTradeDate < a.o.dt.date.today() or lastTradeType == "sell" or float(a.getPrice(e['symbol'])) / avgBuyPrice >= 1.75 ): #prevent selling on the same day as a buy (only sell if only other trade today was a sell or price increased substantially) buyPrice = avgBuyPrice closePrice = float(e['lastday_price']) #curPrice = float(e['current_price']) curPrice = a.getPrice(e['symbol']) maxPrice = 0 #setup jump dates/info about the held positions (reset in markandupdate() and at the beginning of the program) if (e['symbol'] not in jumpDates and e['symbol'] in latestTrades['doubleJump'] ): #only update if not already present jumpDates[e['symbol']] = a.o.goodBuy(e['symbol'], 260) #TODO: add another check here that if it does have an error, try updating it again (especially if few points available) #elif(jumpDates[e['symbol']]!= <some date format>): then do the thing also # jumpDates[e['symbol']] = a.o.goodBuy(e['symbol'],260) buyInfo = jumpDates[e[ 'symbol']] #TODO: phase out buyInfo in lieu of just jumpDates index totalChange = round(curPrice / buyPrice, 2) dayChange = round(curPrice / closePrice, 2) try: lastJump = a.o.dt.datetime.strptime(buyInfo, "%m/%d/%Y").date() #adjust selling targets based on date to add a time limit #after some weeks since the initial jump, the sell values should reach 1 after some more weeks #piecewise function: if less than time to start squeezing, remain constant, else start squeezing linearily per day sellUp = mainSellUp if ( a.o.dt.date.today() < lastJump + a.o.dt.timedelta( float(a.o.c['Sell Params']['startSqueeze']) * 7) ) else mainSellUp - (mainSellUp - 1) * ( a.o.dt.date.today() - (lastJump + a.o.dt.timedelta( float(a.o.c['Sell Params']['startSqueeze']) * 7)) ).days / (float(a.o.c['Sell Params']['squeezeTime']) * 7) sellDn = mainSellDn if ( a.o.dt.date.today() < lastJump + a.o.dt.timedelta( float(a.o.c['Sell Params']['startSqueeze']) * 7) ) else mainSellDn - (mainSellDn - 1) * ( a.o.dt.date.today() - (lastJump + a.o.dt.timedelta( float(a.o.c['Sell Params']['startSqueeze']) * 7)) ).days / (float(a.o.c['Sell Params']['squeezeTime']) * 7) #sellUp change of 0 if <=5 weeks after initial jump, -.05 for every week after 6 weeks for a min of 1 # sellUp = round(max(1,mainSellUp-.05*max(0,int((a.o.dt.date.today()-(lastJump+a.o.dt.timedelta(6*7))).days/7))),2) #sellDn change of 0 if <=5 weeks after initial jump, +.05 for every week after 6 weeks for a max of 1 # sellDn = round(min(1,mainSellDn+.05*max(0,int((a.o.dt.date.today()-(lastJump+a.o.dt.timedelta(6*7))).days/7))),2) print( f"{e['symbol']}\t{bcolor.FAIL if totalChange<1 else bcolor.OKGREEN}{totalChange}{bcolor.ENDC}\t\t{bcolor.FAIL if dayChange<1 else bcolor.OKGREEN}{dayChange}{bcolor.ENDC}\t\t{round(sellUp,2)} & {round(sellDn,2)}\t{lastJump}\t{lastJump+a.o.dt.timedelta(5*7)}\t" ) except Exception: sellUp = mainSellUp sellDn = mainSellDn print( f"{e['symbol']}\t{bcolor.FAIL if totalChange<1 else bcolor.OKGREEN}{totalChange}{bcolor.ENDC}\t\t{bcolor.FAIL if dayChange<1 else bcolor.OKGREEN}{dayChange}{bcolor.ENDC}\t\t{round(sellUp,2)} & {round(sellDn,2)}\t{buyInfo}" ) #cut the losses if we missed the jump or if the price dropped too much if ( buyPrice == 0 or curPrice / buyPrice <= sellDn or buyInfo == "Missed jump" ): #TODO: ensure that the stock is part of the DJ algo (should actually also check in the main algo rather then here, though might be good to check both? print("Lost it on " + e['symbol']) print(a.createOrder("sell", e['qty'], e['symbol'])) latestTrades['doubleJump'][e['symbol']] = { "tradeDate": str(a.o.dt.date.today()), "tradeType": "sell", "buyPrice": 0, "shouldSell": False } with open(a.o.c['File Locations']['latestTradesFile'], "w") as f: f.write(a.o.json.dumps(latestTrades, indent=2)) #use e['lastday_price'] to get previous close amount ... or curPrice/float(e['lastday_price'])>=sellUpFromYesterday elif (curPrice / buyPrice >= sellUp or curPrice / closePrice >= sellUp): if ( not e['symbol'] in [t.getName() for t in threading.enumerate()] ): #if the thread is not found in names of the running threads, then start it (this stops multiple instances of the same stock thread) print("Trigger point reached on " + e['symbol'] + ". Seeing if it will go up...") triggerThread = threading.Thread( target=triggeredUpDJ, args=(e, curPrice, buyPrice, closePrice, maxPrice, sellUpDn, latestTrades)) #init the thread triggerThread.setName( e['symbol']) #set the name to the stock symb triggerThread.start() #start the thread
def algo12(): #TODO: fix sellAll instances so that it will only record in the event that we actually made trades f = open("algo12.txt", "r") #contains json info regarding trading j = a.json.loads(f.read()) f.close() symb = j['symb'] d = j["periodDateStart"].split("-") periodStartDate = date(int(d[0]), int(d[1]), int(d[2])) periodStartVal = float(j["periodPortStart"]) d = j["lastTradeDate"].split("-") lastTradeDate = date(int(d[0]), int(d[1]), int(d[2])) lastSellPrice = float(j["lastSellPrice"]) maxPrice = 0 # minPrice = 100000 #may be used later in trying to get the best buy currentPrice = 0 shares2buy = 0 buyPrice = 0 period = 10 #length of period (d) sellUp = 5 sellUpDn = 3 sellDn = 16 # buyDnUp = 1 portGain = 20 portLoss = 25 timeFromClose = 300 #seconds from close to start analyzing to buy timeSinceStart = 300 #seconds from start to analyze to sell (before infrequent checking) shortTime = 2 medTime = 20 longTime = 60 * 10 while True: #while the market is still alive print("\nMarket is alive") print("Today is " + str(date.today()) + ", the period start date is " + str(periodStartDate)) print("Day " + str(nwd(periodStartDate, date.today()) - 1) + " of " + str(period)) while (nwd(periodStartDate, date.today()) - 1 < period): #while within the period print("We're within the period.") [openTime, closeTime] = a.openCloseTimes(str( date.today())) #get the open and close times of today while (a.marketIsOpen() and date.today() > lastTradeDate): #while the market is open on a given day (that we haven't traded yet) print("\nMarket is open, and no trades made yet") print("Time is: " + str(a.dt.now())) if ( a.getShares(symb) > 0 ): #only check to sell if we have shares in the first place print("We have shares") buyPrice = a.getBuyPrice( symb) #set var to avoid lots of redundant calls while ((a.dt.now() - openTime).seconds < timeSinceStart): #while we're near the open time currentPrice = a.getPrice( symb) #set var to avoid lots of redundant calls print( str((a.dt.now() - openTime).seconds) + "s since open | stock change " + str(round((currentPrice / buyPrice - 1) * 100, 2)) + "%") #check frequently to sell if (currentPrice > buyPrice * (1 + sellUp / 100)): #if the stock price has reached the sell limit print("Stock has reached limit - up " + str( round(100 * (currentPrice / buyPrice - 1), 2) + "%")) maxPrice = max(maxPrice, currentPrice) if (currentPrice <= maxPrice * (1 - sellUpDn / 100)): print("Sell up conditions met.") if (a.sellAll(0)): #set trade flag lastTradeDate = date.today() lastSellPrice = currentPrice j['lastTradeDate'] = str(lastTradeDate) j['lastSellPrice'] = lastSellPrice time.sleep( shortTime) #we're excited, so check often else: time.sleep(medTime) #only check every so often if (lastTradeDate < date.today()): portVal = float(a.getAcct()['portfolio_value']) print("Checking portfolio status") if (portVal > periodStartVal * (1 + portGain / 100) or portVal < periodStartVal * (1 - portLoss / 100)): print("Portfolio won or lost - " + str(round(portVal / periodStartVal, 2)) + "%") if (a.sellAll(0)): periodStartDate = a.date.today() periodStartVal = portVal lastTradeDate = a.date.today() lastSellPrice = a.getPrice(symb) j['lastTradeDate'] = str(lastTradeDate) j['lastSellPrice'] = lastSellPrice j['periodStartDate'] = periodStartDate j['poeriodPortStart'] = periodStartVal #record the end of the period data portVal = float(a.getAcct()['portfolio_value']) print("Portfolio Value: $" + str(round(portVal, 2))) f = open("alpacaPortValues.txt", "a") f.write("\n" + str(date.today()) + "," + str(portVal)) f.close() print("Starting period over.") break else: print("Portfolio change: " + str( round((portVal / periodStartVal - 1) * 100, 2)) + "%") else: break if (lastTradeDate < date.today()): print("No trades made yet today.") while (a.timeTillClose() <= timeFromClose): #while we're close to the end of the day print("Close to closing | " + str(a.dt.now()) + " / " + str(closeTime)) #buy if no shares held, or sell if it reaches the sellUp % method currentPrice = a.getPrice(symb) maxPrice = 0 if (a.getShares(symb) == 0): print("No shares held. Buying.") #include buyDnUp & minPrice here shares2buy = int( float(a.getAcct()['buying_power']) / currentPrice) print( a.createOrder("buy", shares2buy, symb, "market", "day")) lastTradeDate = a.date.today() j['lastTradeDate'] = str(lastTradeDate) break elif (currentPrice >= a.getBuyPrice(symb) * (1 + sellUp / 100)): print("Shares still held, and price is going up") while (currentPrice >= maxPrice * (1 - sellUpDn) and a.timeTillClose() > shortTime * 2): print("Time left: " + str(a.timeTillClose( )) + "s | Stock change: " + str( round(currentPrice / a.getBuyPrice(symb), 2) - 1) + "%") currentPrice = a.getPrice(symb) maxPrice = max(maxPrice, currentPrice) time.sleep(shortTime) if ( currentPrice >= maxPrice * (1 - sellUpDn) ): #if the price is still up (hasn't started dropping yet), then wait till next morning to sell print( "Price is still up, but market is closing. Will continue tomorrow." ) else: if (a.sellAll(0)): lastTradeDate = a.date.today() lastSellPrice = currentPrice j['lastTradeDate'] = str(lastTradeDate) j['lastSellPrice'] = lastSellPrice break time.sleep(medTime) #if we're at any other time of the day #check slow - only sell if (lastTradeDate < a.date.today() and a.getShares(symb) > 0): if (a.getPrice(symb) >= a.getBuyPrice(symb) * (1 + sellUp / 100)): print("Price going up") maxPrice = 0 while (currentPrice >= maxPrice * (1 - sellUpDn / 100)): currentPrice = a.getPrice(symb) maxPrice = max(maxPrice, currentPrice) print("Current Price: " + str(currentPrice) + ", Max Price: " + str(maxPrice)) time.sleep(shortTime) if (a.sellAll(0)): lastSellPrice = currentPrice lastTradeDate = a.date.today() j['lastTradeDate'] = str(lastTradeDate) j['lastSellPrice'] = lastSellPrice break time.sleep( min(longTime, abs(a.timeTillClose() - timeFromClose)) ) #in case we're too close to the closing time, we don't want to overrun it else: break # set values and wait for the market to open again print("Done trading for the day.") f = open("algo12.txt", "w") f.write(a.json.dumps(j)) f.close() maxPrice = 0 currentPrice = 0 shares2buy = 0 print("Current Time: " + str(a.marketTime())) print("Will resume in " + str(a.timeTillOpen()) + " seconds") time.sleep(a.timeTillOpen()) #sell all at end of period and reset values print("End of period. Selling all and resetting.") if (a.sellAll(0)): #sell everything at the end of the period #record the end of the period data portVal = float(a.getAcct()['portfolio_value']) print("Portfolio Value: $" + str(round(portVal, 2))) f = open("alpacaPortValues.txt", "a") f.write("\n" + str(date.today()) + "," + str(portVal)) f.close() #record the trading info lastTradeDate = date.today() j['lastTradeDate'] = str(lastTradeDate) j['periodDateStart'] = str(date.today()) j['periodPortStart'] = a.getAcct()['portfolio_value'] maxPrice = 0 currentPrice = 0 shares2buy = 0 f = open("algo12.txt", "w") f.write(a.json.dumps(j)) f.close() print("Current Time: " + str(a.marketTime())) print("Will resume in " + str(a.timeTillOpen()) + " seconds") time.sleep(a.timeTillOpen()) '''
def algo11(): #initial conditions symb = 'xspa' #symbol to work with timeLimit = 10 #trading days since start to stop startDate = date(2020, 5, 6) #day first started investing startPortVal = float( a.getAcct()['portfolio_value']) #starting portfolio value #selling constants (%) portSellUp = 20 portSellDn = 25 stockSellDn = 16 stockSellUp = 2 stockSellUpDn = 1 #timing constants (s) countdown = 10 longwait = 60 * 10 shortWait = 30 #variables tradeMadeToday = False #flag if a trade has been made today currentPortVal = 0 currentStockVal = 0 sellPrice = 0 #price stocks sold at - $/share shares2buy = 0 #number of shares to buy in a given order #this assumes that shares are held of the stock 'symb', or no shares are held at all while (True): maxStockVal = 0 #additional variable to set/reset after the time limit/period #additional functionailty to choose new stocks on some cirteria should go here #at this point, all of the money should be in buying power #make sure that the shares are held in the correct stock, if not, prompt to sell if (a.getShares(symb) == 0 and not tradeMadeToday): if ( len(a.getPos()) ): #this shouldn't ever happen, but just in case, we error check print(str(a.getPos()).replace(',', '\n') + "\n") print("Error: Shares already held other than " + symb) if ( not a.sellAll(1) ): #prompt user to sell all - returns 0 if cancelled, 1 if finished selling sys.exit( "Only shares of '" + symb + "' are valid. Please sell all to proceed." ) #restart if cancelled - program probably won't work otherwise else: #this should happen the most often - if we're sure no stocks are held, then we can buy some if (not a.marketIsOpen() ): #wait until open, if it's not already print("Waiting till open to buy.") time.sleep(a.timeTillOpen()) shares2buy = int( float(acctInfo['buying_power']) / a.getPrice(symb)) print(a.createOrder("buy", shares2buy, symb, "market", "day")) tradeMadeToday = True startDate = date.today() #at this point, we should have as many shares as we can afford while (nwd(startDate, date.today()) <= timeLimit): #as long as we're in the time limit if (not tradeMadeToday and a.marketIsOpen()): currentStockVal = a.getPrice( symb) # if(a.getShares(symb)) else currentStockVal = 0 # if (currentStockVal < (a.getBuyPrice(symb) * (1 - stockSellDn / 100))): print("Lost the stock") a.sellAll(0) sellPrice = a.getPrice(symb) tradeMadeToday = True elif (currentStockVal >= (a.getBuyPrice(symb) * (1 + stockSellUp / 100)) and a.getBuyPrice(symb) > 0): print("Won the stock") while (currentStockVal > (maxStockVal * (1 - stockSellUpDn / 100))): time.sleep(shortwait) currentStockVal = a.getPrice(symb) maxStockVal = max(maxStockVal, currentStockVal) print("Current Stock Value: " + str(currentStockVal) + ", Sell price:" + str(maxStockVal * (1 - stockSellUpDn / 100))) a.sellAll(0) tradeMadeToday = True acctInfo = a.getAcct() currentPortVal = float(acctInfo['portfolio_value']) if (currentPortVal <= startPortVal * (1 - portSellDn / 100)): print("Lost the portfolio") a.sellAll(0) sellPrice = a.getPrice(symb) # tradeMadeToday = True break elif (currentPortVal >= startPortVal * (1 + portSellUp / 100)): print("Won the portfolio!") a.sellAll(0) sellPrice = a.getPrice(symb) # tradeMadeToday = True break if (not tradeMadeToday and a.getShares(symb) == 0): print("No trades today, and no shares held, so we're buying.") shares2buy = int( float(acctInfo['buying_power']) / a.getPrice(symb)) print(a.createOrder('buy', shares2buy, symb, 'market', 'day')) if (a.marketIsOpen() and not tradeMadeToday ): #this enforces 1 trade per day only during market open print( "Market is open, and no trades made today - Current Portfolio Value Change: " + str(a.getPortfolioChange(startPortVal)) + "%") time.sleep(longwait) else: print(str(timeTillOpen()) + " seconds till open. Be patient.") time.sleep(timeTillOpen() - countdown) tradeMadeToday = False #reset for the start of a new day for i in range(countdown, 0, -1): print(i) time.sleep(1) print("Welcome to day " + str(nwd(startDate, date.today())) + " of " + str(timeLimit) + " - Current Portfolio Value: " + a.getAcct()['portfolio_value'] + " | " + str(a.getPortfolioChange(startPortVal)) + "% from start of period.") print("End of Period. Selling all and starting over.") a.sellAll(0) tradeMadeToday = True startPortVal = float(a.getAcct()['portfolio_value']) startDate = date.today()
def algo10(): symb = 'SD' #ticker symbol length = 10 #days to hold out for sellUp = 9 #sell if the stock is up this far sellDn = 19 #sell if the stock falls this far # startPortfolio = float(a.getAcct()["portfolio_value"]) #portfolio balance at the beginning startPortfolio = 100.0 portfolioGain = 20 #if portfolio value gains by this %, sell and wait till end of period portfolioLoss = 50 #if portfolio value falls by this %, sell and wait till end of period buyPrice = a.getBuyPrice(symb) #init last buy price sellPrice = 0 #init last sell price sharesHeld = a.getShares(symb) #get current held shares of the stock # startDate = date(2020,4,27) marketTime = a.marketTime() #do this to reduce number of API calls startDate = date(marketTime[0], marketTime[1], marketTime[2]) #date of initial investments today = date(marketTime[0], marketTime[1], marketTime[2]) #date to be contiuously updated # filename = "/srv/http/portfolio.json" #used on the serve to display public data while ((today - startDate).days <= length): #while within the period # marketTime = a.marketTime() # today = date(marketTime[0],marketTime[1],marketTime[2]) #set today print("Day " + str((today - startDate).days) + " of " + str(length)) #show the current day # f = open(filename,'w') #open the json file to write to # f.write(a.json.dumps({"portfolioIncrease":float(a.getAcct()["portfolio_value"])/startPortfolio, "period":length,"daysIn":(today-startDate).days})) #write the json data for the server # f.close() #close the json file tradeMade = 0 #reset daily trade counter if (a.marketIsOpen()): #check portfolio value if (float(a.getAcct()["portfolio_value"]) >= ((1 + portfolioGain / 100) * startPortfolio)): sellPrice = a.getPrice(symb) a.sellAll(0) tradeMade = 1 print("Win Time: " + str(today - startDate) + " days") sharesHeld = a.getShares(symb) break elif ((float(a.getAcct()["portfolio_value"]) <= (1 - portfolioLoss / 100)) and (sharesHeld > 0)): print( "Portfolio Failed at " + str(a.marketTime()) + " - Current Value: " + a.getAcct()["portfolio_value"]) #let me know what happened sellPrice = a.getPrice(symb) a.sellAll(0) tradeMade = 1 sharesHeld = a.getShares(symb) #check stock value sharesHeld = a.getShares(symb) #get currently held shares stockVal = a.getPrice(symb) # get the stock's current value if ( a.getShares(symb) == 0 and stockVal >= sellPrice ): #if we don't have shares, and and the price has increased since the last sale, buy buyPrice = int( float(a.getAcct()['buying_power']) / stockVal) #set "buy price", this is actually shares to buy print(a.createOrder("buy", buyPrice, symb, "market", "day")) #may have to make a limit buy buyPrice = float( a.getBuyPrice(symb)) #get actual price bought at elif ( sharesHeld > 0 and (stockVal >= (1 + sellUp / 100) * buyPrice or stockVal <= (1 - sellDn / 100) * buyPrice) ): #if shares are held and their value is sufficiently different to sell if (not tradeMade): #if a trade hasn't been made yet today if (today == startDate): #on the first day we buy #buy as much as we can afford if (sharesHeld == 0): #if no shares held, buy some sharesHeld = int( float(a.getAcct()['buying_power']) / a.getPrice(symb) ) #set # of shares to purchase based on price and current buying power print( a.createOrder( "buy", sharesHeld, symb, "market", "day")) #may have to make a limit buy buyPrice = float(a.getBuyPrice( symb)) #get actual price bought at sharesHeld = a.getShares( symb) #get actual shares held tradeMade = 1 #indicate that a trade has been made today else: #it's not the first day anymore #check portfolio value if (float(a.getAcct()["portfolio_value"]) >= ((1 + portfolioGain / 100) * startPortfolio) ): #if portfolio reached target gain sellPrice = a.getPrice(symb) #get appx sell price a.sellAll(0) #sell everything tradeMade = 1 #set the flag print("Win Time: " + str(today - startDate) + " days") sharesHeld = a.getShares( symb ) #update to actual shares held (should be 0) break #stop the loop elif ((float(a.getAcct()["portfolio_value"]) <= (1 - portfolioLoss / 100)) and (sharesHeld > 0)): #if portfolio lost :( print( "Portfolio lost too much. Selling out until we recover." ) sellPrice = a.getPrice(symb) #get appx sell price a.sellAll(0) #sell everything sharesHeld = a.getShares( symb) #get the shares held tradeMade = 1 #set the flag #check stock value stockVal = a.getPrice( symb) # get the stock's current value sharesHeld = a.getShares(symb) #update shares held if ( sharesHeld == 0 and stockVal >= sellPrice ): # if we don't have shares and the price has increased from the last sale (i.e. has recovered from a slide) buyPrice = int( float(a.getAcct()['buying_power']) / stockVal) #this is actually shares to buy print( a.createOrder( "buy", buyPrice, symb, "market", "day")) #may have to make a limit buy buyPrice = float(a.getBuyPrice( symb)) #get actual price bought at elif ( sharesHeld > 0 and (stockVal >= (1 + sellUp / 100) * buyPrice or stockVal <= (1 - sellDn / 100) * buyPrice) ): #if we have shares and it's greater or less than our initial buying price print("Lost the stock :/") if stockVal <= ( 1 - sellDn / 100) * buyPrice else print( "Won the stock :)") a.sellAll(0) #sell everything else: #market closed print("Done trading for the day.") time.sleep(60 * 15) print( str(a.marketTime()) + " - portfolio Value: " + a.getAcct()["portfolio_value"]) print(str(round(timeTillOpen() / 60, 2)) + " minutes till open.") time.sleep(60 * 30) if timeTillOpen() > (60 * 30) else time.sleep(60 * 5)