def evaluateStocksWithBuyDateAndSellDate(buyDate, sellDate, M=3, N=4, price=10.0, volume=1000, dyield=(0.1, 20), peratio=(0.1, 100), pbratio=0, revenue=(10, 100), YoY=(10, 100), MA=20, extraDays=2, shouldBeStrictlyIncreasing=True, interval=(0.6, 25)): readMonthlyRevenueFromDictionary() result = findStocksWithStrictlyIncreasingMonthlyAveragedRevenue(M, N) buyDatePrices = stockInfo.generateStockPricesDictionaryByDate(buyDate) sellDatePrices = stockInfo.generateStockPricesDictionaryByDate(sellDate) result = filtering(result, buyDatePrices, price, volume, dyield, peratio, pbratio, revenue, YoY) result = filterUsingMA(result, buyDate, MA, extraDays, shouldBeStrictlyIncreasing, interval) evaluation(result, buyDatePrices, sellDatePrices) if (buyDatePrices['2330'].date <= datetime.datetime( endDate.year, endDate.month, 10)): print("!!!!!!! Warning: Buy date is prior to revenue releasing date\n")
def evaluateFilteredStocksWithProfit(evaluateDate, sellDate, trackbackDates=90): bband = calculateBBands(evaluateDate, trackbackDates=trackbackDates) bband = filterPriceHigherThanUpper(bband) bband = filterHighestPriceForDays(bband) bband = filterByMAandVolume(bband, evaluateDate) buyDate = evaluateDate + relativedelta(days=1) d1 = stockInfo.generateStockPricesDictionaryByDate(buyDate) d2 = stockInfo.generateStockPricesDictionaryByDate(sellDate) for i in bband: profit = (d2[i].price - d1[i].price) * 100 / d1[i].price averageWidth = 0 for j in range(30): averageWidth = averageWidth + ( bband[i][j].upper - bband[i][j].MA) * 100 / bband[i][j].MA averageWidth = averageWidth / 30 print("%3d%% %s %.1f%%" % (profit, i, averageWidth)) c = input('show plot (y/n)?') if (c == 'y'): for i in bband: plotBBand(bband, i)
def calculateBBands( date=datetime.datetime.now(), trackbackDates=90, N=20, # days to make MA K=2): # amplitude of band in stdev latestDate = stockInfo.generateStockPricesDictionaryByDate( date)['2330'].date datesNeeded = trackbackDates + N - 1 day = 1 stockList = {} while day <= datesNeeded: stockPrices = stockInfo.generateStockPricesDictionaryByDate( date, autoCorrectDate=False) if (stockPrices != None): stockDict.append(stockPrices) for stockItem in stockPrices: if (stockItem in stockList): stockList[stockItem] = np.append( stockList[stockItem], stockPrices[stockItem].price) else: stockList[stockItem] = np.array( stockPrices[stockItem].price) day = day + 1 date = date - relativedelta(days=1) bbandList = {} stockListCopy = stockList.copy() for stockItem in stockListCopy: try: if (len(stockList[stockItem]) != datesNeeded): del stockList[stockItem] continue except TypeError: # raises TypeError when using len(ndarray) ndarray has len 1 del stockList[stockItem] continue bbandList[stockItem] = [] for i in range(0, trackbackDates): n = stockList[stockItem][i:i + N] mean = n.mean() s = n.std() bbandList[stockItem].append( bband(stockList[stockItem][i], mean, mean + K * s, mean - K * s)) print("Latest date %d/%02d/%02d" % (latestDate.year, latestDate.month, latestDate.day)) return bbandList
def evaluation(bbandList, buyDate, sellDate): d1 = stockInfo.generateStockPricesDictionaryByDate(buyDate) d2 = stockInfo.generateStockPricesDictionaryByDate(sellDate) averageProfit = 0 for stockItem in bbandList: profit = (d2[stockItem].price - d1[stockItem].price) * 100 / d1[stockItem].price averageProfit = averageProfit + profit print("%3d%% %s" % (profit, stockItem)) print("Average profit: %3d%%" % (averageProfit / len(bbandList)))
def loadPredictData(): print("Loading predict data from {}/{}/{} to {}/{}/{}...".format( startPredictDate.year, startPredictDate.month, startPredictDate.day, endPredictDate.year, endPredictDate.month, endPredictDate.day)) x = [ ] # price, open, high, low, volume, transactions, dyield, peratio, pbratio y = [] # the price after 'predictDays' incrementDay = datetime.timedelta(days=1) iterateDate = startPredictDate while iterateDate <= endPredictDate: d = stockInfo.generateStockPricesDictionaryByDate(iterateDate, False) if (d != None): tempX = [ d[stockId].price, d[stockId].open, d[stockId].high, d[stockId].low, d[stockId].volume, d[stockId].transactions, d[stockId].dyield, d[stockId].peratio, d[stockId].pbratio ] x.append(tempX) y.append(d[stockId].price) iterateDate += incrementDay return x, y
def filterUsingMA(stockList, dateOfMA, MA=20, extraDays=2, shouldBeStrictlyIncreasing=False, interval=0): maList = stockInfo.generateMovingAverageDictionaryForAllStocksByDate( date=dateOfMA, MA=MA, extraDays=extraDays) d = stockInfo.generateStockPricesDictionaryByDate(dateOfMA) stockListCopy = stockList.copy() for stock in stockListCopy: strictlyIncreasing = True if (shouldBeStrictlyIncreasing): try: # stocks not open in any workday should be lack in maList a = all(maList[stock[0]][i] >= maList[stock[0]][i + 1] for i in range(0, extraDays - 1)) b = d[stock[0]].price >= maList[stock[0]][0] strictlyIncreasing = a and b except KeyError: stockList.remove(stock) continue if (not strictlyIncreasing): stockList.remove(stock) continue try: # stocks not open in any workday should be lack in maList progress = (maList[stock[0]][0] - maList[stock[0]][extraDays - 1] ) * 100 / maList[stock[0]][extraDays - 1] except KeyError: stockList.remove(stock) continue if (interval != 0): if (type(interval) == tuple or type(interval) == list): if (not (interval[0] <= progress and progress <= interval[1])): stockList.remove(stock) else: if (progress < interval): stockList.remove(stock) stock.append(maList[stock[0]][0]) stock.append(progress) print("%d stocks found after MA filter" % (len(stockList))) return stockList # ['2330', growth, YoY, MoM, MA on buy date, MA increase]
class MDMP(): def __init__(self, name, price, volume, date): self.name = name self.maxDate = None self.maxPrice = None self.surpassPrice = price self.surpassVolume = volume self.surpassDate = date record = {} traceDate = surpassDate d = stockInfo.generateStockPricesDictionaryByDate(surpassDate, False) for stockId in d: record[stockId] = MDMP(d[stockId].name, d[stockId].high, d[stockId].volume, d[stockId].date) traceDate = traceDate - datetime.timedelta(days=1) while startDate <= traceDate: d = stockInfo.generateStockPricesDictionaryByDate(traceDate, False) if (d != None): for stockId in d: try: if (d[stockId].high > record[stockId].surpassPrice and record[stockId].maxDate == None): record[stockId].maxPrice = d[stockId].high record[stockId].maxDate = d[stockId].date except KeyError:
def evaluateCertainStock(stockIds, buyDate, sellDate=None): if (type(stockIds) != list): stockIds = [stockIds] compareDate = datetime.datetime(buyDate.year, buyDate.month, 10) if (buyDate < compareDate): now = buyDate - relativedelta(months=2) else: now = buyDate - relativedelta(months=1) revenue = { } # should be initialized in order to generate multiple rounds within an execution for stockItem in stockIds: revenue[stockItem] = [] for k in range(0, 3): for reportFile in monthlyReportFile: filename = monthlyReportFolder + reportFile + '%d%02d.csv' % ( now.year, now.month) # determine if the report is intact while (not os.path.exists(filename)): now = now - relativedelta(months=1) print("Revenue report not published yet. Take %d%02d" % (now.year, now.month)) filename = monthlyReportFolder + reportFile + '%d%02d.csv' % ( now.year, now.month) print(filename) df = pd.read_csv(filename) df = df[['公司代號', '公司名稱', '營業收入-當月營收', '產業別']] for i in range(0, len(df)): id = str(df.loc[i]['公司代號']) if (not (id in stockIds)): continue # not filtering out construction stocks r = df.loc[i]['營業收入-當月營收'] revenue[id].append(r) if (k == 0): now = now - relativedelta(months=1) elif (k == 1): now = now - relativedelta(years=1) now = now + relativedelta(months=1) if (sellDate != None): buy = stockInfo.generateStockPricesDictionaryByDate(buyDate) sell = stockInfo.generateStockPricesDictionaryByDate(sellDate) buyMA = stockInfo.generateMovingAverageDictionaryForAllStocksByDate( buyDate, MA=20, extraDays=2) buyDate = buy['2330'].date print( "\n獲利\t殖利\t本益\t淨比\tYoY\tMoM\t代號\t公司\t股價%d/%02d/%02d\t股價%d/%02d/%02d\t成交量\tMA20\tMA20Progress" % (buyDate.year, buyDate.month, buyDate.day, sellDate.year, sellDate.month, sellDate.day)) print( "-----------------------------------------------------------------------" ) averageProfit = 0 count = 0 for stockItem in revenue: try: if (revenue[stockItem][0] == 0 or revenue[stockItem][1] == 0 or revenue[stockItem][2] == 0): continue profit = (sell[stockItem].price - buy[stockItem].price) * 100 / buy[stockItem].price MoM = (revenue[stockItem][0] - revenue[stockItem][1]) * 100 / revenue[stockItem][1] YoY = (revenue[stockItem][0] - revenue[stockItem][2]) * 100 / revenue[stockItem][2] MA = buyMA[stockItem][0] MAProgress = (MA - buyMA[stockItem][1]) * 100 / buyMA[stockItem][1] except: continue averageProfit = averageProfit + profit count = count + 1 print( "%3d%%\t%3.2f%%\t%5.2f\t%4.2f\t%3d%%\t%3d%%\t%s\t%6s\t%7.2f\t%7.2f\t%10d\t%.2f\t%.3f%%" % (profit, buy[stockItem].dyield, buy[stockItem].peratio, buy[stockItem].pbratio, YoY, MoM, stockItem, buy[stockItem].name, buy[stockItem].price, sell[stockItem].price, buy[stockItem].volume, MA, MAProgress)) averageProfit = averageProfit / count print("\nTotal %d stocks\nAverage Profit: %.1f%%\n" % (count, averageProfit)) else: buy = stockInfo.generateStockPricesDictionaryByDate(buyDate) buyMA = stockInfo.generateMovingAverageDictionaryForAllStocksByDate( buyDate, MA=20, extraDays=2) print( "殖利\t本益\t淨比\tYoY\tMoM\t代號\t公司\t股價%d/%02d/%02d\t成交量\tMA20\tMA20Progress" % (buyDate.year, buyDate.month, buyDate.day)) print( "-----------------------------------------------------------------------" ) count = 0 for stockItem in revenue: try: MoM = (revenue[stockItem][0] - revenue[stockItem][1]) * 100 / revenue[stockItem][1] YoY = (revenue[stockItem][0] - revenue[stockItem][2]) * 100 / revenue[stockItem][2] MA = buyMA[stockItem][0] MAProgress = (MA - buyMA[stockItem][1]) * 100 / buyMA[stockItem][1] except: continue count = count + 1 print( "%3.2f%%\t%5.2f\t%4.2f\t%3d%%\t%3d%%\t%s\t%6s\t%7.2f\t%10d\t%.2f\t%.3f%%" % (buy[stockItem].dyield, buy[stockItem].peratio, buy[stockItem].pbratio, YoY, MoM, stockItem, buy[stockItem].name, buy[stockItem].price, buy[stockItem].volume, MA, MAProgress)) print("\nTotal %d stocks\n" % (count))
def prediction(M, N, buyDate=datetime.datetime.now(), price=10.0, volume=1000, dyield=(0.1, 3), peratio=(0.1, 100), pbratio=0, revenue=(10, 100), YoY=(10, 100), MA=20, extraDays=2, shouldBeStrictlyIncreasing=True, interval=(0.8, 20)): generateMonthlyRevenueToDictionary(M=M, N=N, end=buyDate - relativedelta(months=1)) readMonthlyRevenueFromDictionary() result = findStocksWithStrictlyIncreasingMonthlyAveragedRevenue(M, N) while True: buyDatePrices = stockInfo.generateStockPricesDictionaryByDate(buyDate) if (buyDatePrices == None ): # specific date stock price report not released yet buyDate = buyDate - relativedelta(days=1) else: print("take %d/%02d/%02d in prediction" % (buyDate.year, buyDate.month, buyDate.day)) break buyDate = buyDatePrices['2330'].date result = filtering(result, buyDatePrices, price=price, volume=volume, dyield=dyield, peratio=peratio, pbratio=pbratio, revenue=revenue, YoY=YoY) result = filterUsingMA( result, buyDate, MA=MA, extraDays=extraDays, shouldBeStrictlyIncreasing=shouldBeStrictlyIncreasing, interval=interval) # showing filtering result count = 0 print( "殖利\t本益\t淨比\t營收\tYoY\tMoM\t代號\t公司\t股價%d/%02d/%02d\t成交量\tMA20\tMA20Progress" % (buyDate.year, buyDate.month, buyDate.day)) print( "-----------------------------------------------------------------------" ) for stock in result: count = count + 1 print( "%3.2f%%\t%5.2f\t%4.2f\t%3d%%\t%3d%%\t%3d%%\t%s\t%6s\t%7.2f\t%10d\t%.2f\t%.3f%%" % (buyDatePrices[stock[0]].dyield, buyDatePrices[stock[0]].peratio, buyDatePrices[stock[0]].pbratio, stock[1], stock[2], stock[3], stock[0], buyDatePrices[stock[0]].name, buyDatePrices[stock[0]].price, buyDatePrices[stock[0]].volume, stock[4], stock[5])) print("\n%d stocks found\n" % (count))
date = datetime.datetime(2019, 8, 1) while date >= datetime.datetime(2014, 1, 1): generateMonthlyRevenueToDictionary(M=M, N=N, end=date) readMonthlyRevenueFromDictionary() result = findStocksWithStrictlyIncreasingMonthlyAveragedRevenue( M, N) buyDate = endDate + relativedelta(months=1) buyDate = datetime.datetime(buyDate.year, buyDate.month, 11) sellDate = endDate + relativedelta(months=2) sellDate = datetime.datetime(sellDate.year, sellDate.month, 5) buyDatePrices = stockInfo.generateStockPricesDictionaryByDate( buyDate) sellDatePrices = stockInfo.generateStockPricesDictionaryByDate( sellDate) result = filtering( result, buyDatePrices, 10.0, 500, dyield=(0.01, 20), peratio=(0.01, 200), pbratio=(0.01, 100), revenue=(1, 300), YoY=(0.01, 400)) # best from 2019-06 monthly revenue, M=3, N=4 result = filterUsingMA(result, buyDate, 20, 2, False) '''
c = input("id: ") if (c == 'end'): break try: plotStocks(c, datetime.datetime(2020, 1, 2), 90) except: continue elif (sys.argv[1] == '3'): startDate = datetime.datetime(2019, 1, 1) endDate = datetime.datetime(2019, 10, 1) stock = {} date = startDate while date <= endDate: d = stockInfo.generateStockPricesDictionaryByDate(date, False) if (d != None): for item in d: if (item in stock): stock[item] = np.append(stock[item], d[item].price) else: stock[item] = np.array(d[item].price) date = date + relativedelta(days=1) for item in stock: maxPrice = max(stock[item]) minPrice = min(stock[item]) averagePrice = sum(stock[item]) / len(stock[item]) upwidth = (maxPrice - averagePrice) / averagePrice * 100 downwidth = (averagePrice - minPrice) / averagePrice * 100