def get_monthRP(date_end, date_start, Number): #end = 後面時間 start = 前面時間 Number = 股票號碼 date_end_str = str(date_end.year()) + '-' + str( date_end.month()) + '-' + str(date_end.day()) m_date_end = datetime.strptime(date_end_str, "%Y-%m-%d") date_start_str = str(date_start.year()) + '-' + str( date_start.month()) + '-' + str(date_start.day()) m_date_start = datetime.strptime(date_start_str, "%Y-%m-%d") stockNum = Number data_result = None while (m_date_start <= m_date_end): try: monthRP_temp = get_stock_history.get_stock_monthly_report( stockNum, m_date_start) except: print(str(m_date_start) + "月營收未出喔") m_date_start = tools.changeDateMonth(m_date_start, +1) continue monthRP_temp.insert(0, '日期', m_date_start) monthRP_temp['當月營收'] = int(monthRP_temp['當月營收']) / 1000 data_result = pd.concat([data_result, monthRP_temp]) m_date_start = tools.changeDateMonth(m_date_start, +1) if m_date_start > m_date_end and m_date_end.year == m_date_start.year: try: monthRP_temp = get_stock_history.get_stock_monthly_report( stockNum, m_date_start) monthRP_temp.insert(0, '日期', m_date_start) monthRP_temp['當月營收'] = int(monthRP_temp['當月營收']) / 1000 data_result = pd.concat([data_result, monthRP_temp]) except: print(str(m_date_start) + "月營收未出喔") data_result.set_index('日期', inplace=True) return data_result
def get_ROE_range( time, ROE_start, ROE_end, data=pd.DataFrame()): #time = 取得資料的時間 ROE_start = ROE最小值 ROE_end ROE最大值 print('get_ROE_rang: start') ROE_data = pd.DataFrame(columns=['公司代號', 'ROE']) #股東權益=資產 - 負債 (資產負債表中) #稅後淨利 = (本期綜合損益) if ROE_start == ROE_end == 0: return ROE_data if ROE_end < 0 or ROE_start < 0 or ROE_end < ROE_start: print("ROE range number wrong!") return ROE_data ROE_date = time All_ROE = data if type(time) == str: ROE_date = datetime.strptime(time, "%Y-%m-%d") if ROE_date.month in [1, 2, 3]: Use_ROE_date = datetime(ROE_date.year - 1, 12, 1) else: Use_ROE_date = datetime( ROE_date.year, tools.changeDateMonth(ROE_date, -3).month, tools.check_monthDate( tools.changeDateMonth(ROE_date, -3).month, ROE_date.day)) BOOK_data = get_allstock_financial_statement(Use_ROE_date, FS_type.BS) CPL_data = get_allstock_financial_statement(Use_ROE_date, FS_type.CPL) if All_ROE.empty == True: All_ROE = BOOK_data for index, row in All_ROE.iterrows(): if check_no_use_stock(index): continue Temp_Book = int(BOOK_data.at[index, '權益總額']) Temp_CPL = int(CPL_data.at[index, "本期綜合損益總額(稅後)"]) Temp_ROE = round((Temp_CPL / Temp_Book), 4) * 100 if Temp_ROE < 0: continue print('get_ROE_range:' + str(index) + '--' + str(Temp_CPL) + '/' + str(Temp_Book) + '= ' + str(Temp_ROE)) if (Temp_ROE > ROE_start) and (Temp_ROE < ROE_end): Temp_number = int(index) ROE_data = ROE_data.append({ '公司代號': Temp_number, 'ROE': Temp_ROE }, ignore_index=True) ROE_data['公司代號'] = ROE_data['公司代號'].astype('int') ROE_data.set_index('公司代號', inplace=True) print('get_ROE_rang: end') return ROE_data
def get_monthRP_up(time, avgNum, upNum): #time = 取得資料的時間 avgNum = 平滑曲線月份 upNum = 連續成長月份 print('get_monthRP_up: start:' + str(time)) fileName = str(time.year) + str(time.month) + str(avgNum) + str(upNum) if fileName in load_memery: print('get_monthRP_up: end') return load_memery[fileName] data = {} for i in range(avgNum + upNum): temp_now = tools.changeDateMonth(time, -(i + 1)) data['%d-%d-01' % (temp_now.year, temp_now.month)] = get_allstock_monthly_report(temp_now) result = pd.DataFrame({k: result['當月營收'] for k, result in data.items()}).transpose() result.index = pd.to_datetime(result.index) result = result.sort_index() method2 = result.rolling(avgNum, min_periods=avgNum).mean() method2 = (method2 > method2.shift()).iloc[-upNum:].sum() final_result = method2[method2 >= upNum] final_result = pd.DataFrame(final_result) try: final_result = final_result.drop('全部國內上市公司合計', axis=0) except: final_result = final_result final_result = final_result.rename(index=int) final_result.index.name = '公司代號' load_memery[str(time.year) + str(time.month) + str(avgNum) + str(upNum)] = final_result print('get_monthRP_up: end') return final_result
def button_pick_click(): volume_date = tools.QtDate2DateTime(myshow.date_endDate.date()) GPM = mypick.input_GPM.toPlainText() OPR = mypick.input_OPR.toPlainText() EPS = mypick.input_EPS.toPlainText() RPS = mypick.input_RPS.toPlainText() resultAllFS = pd.DataFrame() resultAllFS = get_financial_statement(volume_date, GPM, OPR, EPS, RPS) if volume_date.isoweekday() == 6: volume_date = volume_date + timedelta(days=-1) #加一天 elif volume_date.isoweekday() == 7: volume_date = volume_date + timedelta(days=-2) #加2天 else: pass price_data = get_stock_history.get_price_range( volume_date, int(mypick.input_price_high.toPlainText()), int(mypick.input_price_low.toPlainText()), resultAllFS) if price_data.empty == False: resultAllFS = tools.MixDataFrames({ 'pick': resultAllFS, 'recordHigh': price_data }) resultAllFS = resultAllFS.dropna(axis=0, how='any') resultAllFS = get_volume(int(mypick.input_volum.toPlainText()), tools.changeDateMonth(volume_date, 0), resultAllFS) mypick.treeView_pick.setModel( creat_treeView_model(mypick.treeView_pick, pick_titalList)) #設定treeView功能 set_treeView2(mypick.treeView_pick.model(), resultAllFS)
def get_allstock_financial_statement(start, type): #爬某季所有股票歷史財報 print("get_allstock_financial_statement:" + str(type)) for i in range(12): try: season = int(((start.month - 1) / 3) + 1) if season == 4: season = 3 if start < datetime(start.year, 11, 14): season = 2 start = tools.changeDateMonth(start, -6) else: start = tools.changeDateMonth(start, -3) elif season == 3: season = 2 if start < datetime(start.year, 8, 14): season = 1 start = tools.changeDateMonth(start, -6) else: start = tools.changeDateMonth(start, -3) elif season == 2: season = 1 if start < datetime(start.year, 5, 15): season = 4 start = tools.changeDateMonth(start, -6) else: start = tools.changeDateMonth(start, -3) elif season == 1: season = 4 if start < datetime(start.year, 3, 31): season = 3 start = tools.changeDateMonth(start, -6) else: start = tools.changeDateMonth(start, -3) fileName = filePath + '/' + fileName_season + '/' + str( start.year) + "-season" + str( season) + "-" + type.value + ".csv" if fileName in load_memery: return load_memery[fileName] if os.path.isfile(fileName) == True: print("已經有" + str(start.month) + "月財務報告") break financial_statement(start.year, season, type) print("下載" + str(start.month) + "月財務報告OK") break except: print(str(start.month) + "月財務報告未出跳下一個月") start = tools.changeDateMonth(start, -1) continue stock = pd.read_csv(fileName, index_col='公司代號', parse_dates=['公司代號']) load_memery[fileName] = stock return stock
def get_price_range(time, high, low, data=pd.DataFrame()): #time = 取得資料的時間 high = 最高價 low = 最低價 print('get_price_rang: start') price_data = pd.DataFrame(columns=['公司代號', 'price']) if high == low == 0: return price_data if high < low or high < 0 or low < 0: print("price range number wrong!") return price_data price_time = time All_price = data if type(time) == str: price_time = datetime.strptime(time, "%Y-%m-%d") if price_time.month in [1, 2, 3]: Use_price_time = datetime(price_time.year - 1, 12, 1) else: Use_price_time = datetime( price_time.year, tools.changeDateMonth(price_time, -3).month, tools.check_monthDate( tools.changeDateMonth(price_time, -3).month, price_time.day)) if All_price.empty == True: return price_data for index, row in All_price.iterrows(): if check_no_use_stock(index): continue Temp_price = get_stock_price(index, Use_price_time, stock_data_kind.AdjClose) if Temp_price == None: continue if (Temp_price > low) and (Temp_price < high): Temp_number = int(index) price_data = price_data.append( { '公司代號': Temp_number, 'price': Temp_price }, ignore_index=True) price_data['公司代號'] = price_data['公司代號'].astype('int') price_data.set_index('公司代號', inplace=True) print('get_price_rang: end') return price_data
def get_allstock_monthly_report(start): #爬某月所有股票月營收 if start.day < 15: #還沒超過15號,拿前一個月 print("get_allstock_monthly_report:未到25號取上個月報表") start = tools.changeDateMonth(start, -1) year = start.year fileName = filePath + '/' + fileName_monthRP + '/' + str( start.year) + '-' + str(start.month) + 'monthly_report.csv' if fileName in load_memery: return load_memery[fileName] if os.path.isfile(fileName) == False: # 假如是西元,轉成民國 if year > 1990: year -= 1911 url = 'https://mops.twse.com.tw/nas/t21/sii/t21sc03_' + str( year) + '_' + str(start.month) + '_0.html' if year <= 98: url = 'https://mops.twse.com.tw/nas/t21/sii/t21sc03_' + str( year) + '_' + str(start.month) + '.html' # 下載該年月的網站,並用pandas轉換成 dataframe r = requests.get(url, headers=tools.get_random_Header()) r.encoding = 'big5-hkscs' dfs = pd.read_html(StringIO(r.text), encoding='big-5') df = pd.concat( [df for df in dfs if df.shape[1] <= 11 and df.shape[1] > 5]) if 'levels' in dir(df.columns): df.columns = df.columns.get_level_values(1) else: df = df[list(range(0, 10))] column_index = df.index[(df[0] == '公司代號')][0] df.columns = df.iloc[column_index] df['當月營收'] = pd.to_numeric(df['當月營收'], 'coerce') df = df[~df['當月營收'].isnull()] df = df[df['公司代號'] != '合計'] df.to_csv(fileName, index=False) # 偽停頓 time.sleep(1.5) df = pd.read_csv(fileName, index_col='公司代號', parse_dates=['公司代號']) load_memery[fileName] = df return df
def get_financial_statement(date, GPM='0', OPR='0', EPS='0', RPS='0'): FS_type = get_stock_history.FS_type.PLA resultAllFS1 = [] resultAllFS2 = [] resultAllFS3 = [] this = pd.DataFrame() FS_type = get_stock_history.FS_type.PLA volume_date = date for i in range(12): try: this = get_stock_history.get_allstock_financial_statement( date, FS_type) print(str(date.month) + "月財務報告OK") break except: print(str(date.month) + "月財務報告未出跳下一個月") date = tools.changeDateMonth(date, -1) continue this1 = this["毛利率(%)"] > float(GPM) this2 = this["營業利益率(%)"] > float(OPR) resultAllFS1 = this[this1 & this2] FS_type = get_stock_history.FS_type.BS this = get_stock_history.get_allstock_financial_statement(date, FS_type) this1 = this["每股參考淨值"] > float(RPS) resultAllFS2 = this[this1] FS_type = get_stock_history.FS_type.CPL this = get_stock_history.get_allstock_financial_statement(date, FS_type) this1 = this["基本每股盈餘(元)"] > float(EPS) resultAllFS3 = this[this1] resultAllFS_temp = pd.merge(resultAllFS1, resultAllFS2, left_index=True, right_index=True) resultAllFS = pd.merge(resultAllFS3, resultAllFS_temp, left_index=True, right_index=True) return resultAllFS
def backtest_KD_pick(mainParament): userInfo = get_user_info.data_user_info(mainParament.money_start, mainParament.date_start, mainParament.date_end) Temp_result_pick = pd.DataFrame(columns=['date', '選股數量']) Temp_table = get_stock_history.get_stock_history(2330, userInfo.start_day, reGetInfo=False, UpdateInfo=False) All_stock_signal = dict() for key, value in get_stock_info.ts.codes.items(): if value.market == "上市" and len(value.code) == 4: if get_stock_history.check_no_use_stock(value.code) == True: print('get_stock_price: ' + str(value.code) + ' in no use') continue table = get_stock_history.get_stock_history(value.code, userInfo.start_day, reGetInfo=False, UpdateInfo=False) table_K, table_D = talib.STOCH(table['High'], table['Low'], table['Close'], fastk_period=50, slowk_period=20, slowk_matype=0, slowd_period=20, slowd_matype=0) table_sma10 = talib.SMA(np.array(table['Close']), 10) table_sma240 = talib.SMA(np.array(table['Close']), 240) signal_buy = (table_K > table_D) signal_sell = (table_K < table_D) signal_sma10 = table.Close < table_sma10 signal_sma240 = table.Close > table_sma240 signal = signal_buy.copy() signal = (signal_sma10 & signal_sma240 & signal_buy) signal[signal_sell] = -1 All_stock_signal[value.code] = signal ROE_record_day = datetime.datetime(2000, 1, 1) buy_data = pd.DataFrame(columns=['Date', '公司代號']).set_index('Date') sell_data = pd.DataFrame(columns=['Date', '公司代號']).set_index('Date') ROE_data = {} jump_day = 240 for index, row in Temp_table.iterrows(): while userInfo.now_day < index: userInfo.add_one_day() if jump_day > 0: jump_day = jump_day - 1 continue if ROE_record_day <= index: ROE_data = {} ROE_record_day = tools.changeDateMonth(index, 1) BOOK_data = get_stock_history.get_allstock_financial_statement( tools.changeDateMonth(index, -3), get_stock_history.FS_type.BS) CPL_data = get_stock_history.get_allstock_financial_statement( tools.changeDateMonth(index, -3), get_stock_history.FS_type.CPL) ROE_data["ROE_data_1"] = pd.DataFrame({ 'ROE_data_1': (CPL_data["本期綜合損益總額(稅後)"] / BOOK_data['權益總額']) * 100 }) BOOK_data = get_stock_history.get_allstock_financial_statement( tools.changeDateMonth(index, -6), get_stock_history.FS_type.BS) CPL_data = get_stock_history.get_allstock_financial_statement( tools.changeDateMonth(index, -6), get_stock_history.FS_type.CPL) ROE_data["ROE_data_2"] = pd.DataFrame({ 'ROE_data_2': (CPL_data["本期綜合損益總額(稅後)"] / BOOK_data['權益總額']) * 100 }) BOOK_data = get_stock_history.get_allstock_financial_statement( tools.changeDateMonth(index, -9), get_stock_history.FS_type.BS) CPL_data = get_stock_history.get_allstock_financial_statement( tools.changeDateMonth(index, -9), get_stock_history.FS_type.CPL) ROE_data["ROE_data_3"] = pd.DataFrame({ 'ROE_data_3': (CPL_data["本期綜合損益總額(稅後)"] / BOOK_data['權益總額']) * 100 }) BOOK_data = get_stock_history.get_allstock_financial_statement( tools.changeDateMonth(index, -12), get_stock_history.FS_type.BS) CPL_data = get_stock_history.get_allstock_financial_statement( tools.changeDateMonth(index, -12), get_stock_history.FS_type.CPL) ROE_data["ROE_data_4"] = pd.DataFrame({ 'ROE_data_4': (CPL_data["本期綜合損益總額(稅後)"] / BOOK_data['權益總額']) * 100 }) mask = tools.MixDataFrames(ROE_data) ROE_data_result = (mask["ROE_data_1"] + mask["ROE_data_2"] + mask["ROE_data_3"] + mask["ROE_data_4"]) / 4 ROE_data_result = ROE_data_result.dropna() ROE_data = mask["ROE_data_1"] > ROE_data_result buy_numbers = [] sell_numbers = [] for i, value in All_stock_signal.items(): try: if value[index] == True: if ROE_data.index.__contains__(int(i)): if ROE_data[int(i)] == True: buy_numbers.append(i) elif value[index] < 0: sell_numbers.append(i) except: #print('error:' + str(index) + ' at ' + str(i)) continue #出場訊號篩選-------------------------------------- if len(userInfo.handle_stock) > 0: Temp_data = userInfo.handle_stock for key, value in list(Temp_data.items()): if sell_numbers.__contains__(key): userInfo.sell_stock(key, value.amount) #入場訊號篩選-------------------------------------- if len(buy_numbers) > 0: Temp_buy = pd.DataFrame(columns={'公司代號', 'volume'}) for number in buy_numbers: volume = get_stock_history.get_stock_price( number, tools.DateTime2String(userInfo.now_day), get_stock_history.stock_data_kind.Volume) Temp_buy = Temp_buy.append({ '公司代號': number, 'volume': volume }, ignore_index=True) Temp_buy = Temp_buy.sort_values(by='volume', ascending=False).set_index('公司代號') userInfo.buy_all_stock(Temp_buy) if len(buy_numbers) != 0: buy_data = buy_data.append({ 'Date': index, '公司代號': buy_numbers }, ignore_index=True) if len(sell_numbers) != 0: sell_data = sell_data.append({ 'Date': index, '公司代號': sell_numbers }, ignore_index=True) #更新資訊-------------------------------------- userInfo.Record_userInfo() userInfo.Recod_tradeInfo() Temp_result_pick = Temp_result_pick.append( { 'date': userInfo.now_day, '選股數量': len(buy_numbers) }, ignore_index=True) buy_data = buy_data.set_index('Date') buy_data.to_csv('buy.csv') sell_data = sell_data.set_index('Date') sell_data.to_csv('sell.csv') #最後總結算---------------------------- Temp_result_pick.set_index('date', inplace=True) Temp_alldata = tools.MixDataFrames( { 'draw': userInfo.Temp_result_draw, 'pick': Temp_result_pick }, 'date') draw_figur.draw_backtest(userInfo.Temp_result_draw.set_index('date')) Temp_alldata = tools.MixDataFrames( { 'all': Temp_alldata, 'userinfo': userInfo.Temp_result_All }, 'date') userInfo.Temp_result_draw.set_index('date').to_csv('backtestdata.csv') userInfo.Temp_trade_info.set_index('date').to_csv('backtesttrade.csv') Temp_alldata.set_index('date').to_csv('backtestAll.csv')
def button_monthRP_Up_click(): #月營收逐步升高篩選 date = tools.QtDate2DateTime(myshow.date_endDate.date()) date_5 = date + timedelta(days=-14) #加一天 if date.isoweekday() == 6: date = date + timedelta(days=-1) #加一天 elif date.isoweekday() == 7: date = date + timedelta(days=-2) #加2天 else: pass GPM = mypick.input_GPM.toPlainText() OPR = mypick.input_OPR.toPlainText() EPS = mypick.input_EPS.toPlainText() RPS = mypick.input_RPS.toPlainText() FS_data = pd.DataFrame() result_data = pd.DataFrame() BOOK_data = pd.DataFrame() PER_data = pd.DataFrame() yield_data = pd.DataFrame() FS_data = get_financial_statement(date, GPM, OPR, EPS, RPS) result_data = get_stock_history.get_monthRP_up( tools.changeDateMonth(date, 0), int(mypick.input_monthRP_smoothAVG.toPlainText()), int(mypick.input_monthRP_UpMpnth.toPlainText())) BOOK_data = get_stock_history.get_PBR_range( tools.changeDateMonth(date, 0), float(mypick.input_PBR_low.toPlainText()), float(mypick.input_PBR_high.toPlainText())) PER_data = get_stock_history.get_PER_range( tools.changeDateMonth(date, 0), float(mypick.input_PER_low.toPlainText()), float(mypick.input_PER_high.toPlainText())) ROE_data = get_stock_history.get_ROE_range( tools.changeDateMonth(date, 0), float(mypick.input_ROE_low.toPlainText()), float(mypick.input_ROE_high.toPlainText())) yield_data = get_stock_history.get_yield_range( tools.changeDateMonth(date, 0), float(mypick.input_yiled_high.toPlainText()), float(mypick.input_yiled_low.toPlainText())) pick_data = FS_data if result_data.empty == False: pick_data = pd.merge(pick_data, result_data, left_index=True, right_index=True, how='left') pick_data = pick_data.dropna(axis=0, how='any') if BOOK_data.empty == False: pick_data = pd.merge(pick_data, BOOK_data, left_index=True, right_index=True, how='left') pick_data = pick_data.dropna(axis=0, how='any') if PER_data.empty == False: pick_data = pd.merge(pick_data, PER_data, left_index=True, right_index=True, how='left') pick_data = pick_data.dropna(axis=0, how='any') if ROE_data.empty == False: pick_data = pd.merge(pick_data, ROE_data, left_index=True, right_index=True, how='left') pick_data = pick_data.dropna(axis=0, how='any') if yield_data.empty == False: pick_data = pd.merge(pick_data, yield_data, left_index=True, right_index=True, how='left') pick_data = pick_data.dropna(axis=0, how='any') price_data = get_stock_history.get_price_range( date, int(mypick.input_price_high.toPlainText()), int(mypick.input_price_low.toPlainText()), pick_data) if price_data.empty == False: pick_data = tools.MixDataFrames({ 'pick': pick_data, 'price': price_data }) pick_data = pick_data.dropna(axis=0, how='any') record_data = get_stock_history.get_RecordHigh_range( date, int(mypick.input_flash_Day.toPlainText()), int(mypick.input_record_Day.toPlainText()), pick_data) if record_data.empty == False: pick_data = tools.MixDataFrames({ 'pick': pick_data, 'recordHigh': record_data }) pick_data = pick_data.dropna(axis=0, how='any') pick_data = get_volume(int(mypick.input_volum.toPlainText()), tools.changeDateMonth(date_5, 0), pick_data) pick_data = pick_data.dropna(axis=0, how='any') print("總挑選數量:" + str(len(pick_data))) mypick.treeView_pick.setModel( creat_treeView_model(mypick.treeView_pick, pick_titalList)) #設定treeView功能 set_treeView2(mypick.treeView_pick.model(), pick_data)