#!/usr/local/bin/python #coding=utf-8 #回测均线策略 import pandas as pd import matplotlib.pyplot as plt import os import numpy as np AVR_SHORT = 12 AVR_LONG = 40 SIGNAL_BUY = 1 #买 SIGNAL_SALE = -1 #卖 SIGNAL_DEFAULT = 0 # 导入csv股票数据,写5日、20日、60日移动平均线 def processEMA(stockCsvPath, stockCsvNewPath): #导入数据,stockCsvPath为在电脑中的路径 stock_data = pd.read_csv(stockCsvPath) # 将数据按照交易日期从远到近排序 stock_data.sort('Date', inplace=True) #=====================计算移动平均线 # 分别计算5日、20日、60日移动平均线 ma_list = [5, 20, 60] # 计算简单算术移动平均线MA - 注意:stock_data['close']为股票每条的收盘价 for ma in ma_list: stock_data['MA_' + str(ma)] = pd.rolling_mean(stock_data['Adj Close'], ma) # 计算指数平滑移动平均线EMA for ma in ma_list: stock_data['EMA_' + str(ma)] = pd.ewma(stock_data['Adj Close'], span=ma) # 将数据按照交易日期从近到远排序 stock_data.sort('Date', ascending=False, inplace=True) stock_data['DIF'] = stock_data['EMA_'+str(ma_list[0])] - stock_data['EMA_'+str(ma_list[-1])] stock_data['DEA_' + str(10)] = pd.ewma(stock_data['DIF'], span=10) # =================================== 将算好的数据输出到csv文件,这里请填写输出文件在您电脑的路径 stock_data.to_csv(stockCsvNewPath, index=False) # 自适应均线 def self_adaptive_ma(stock_data): # 将数据按照交易日期从远到近排序 stock_data.sort('Date', inplace=True) close_price = stock_data['Adj Close'].get_values() high_price = stock_data['High'].get_values() low_price = stock_data['Low'].get_values() longDay = 100 print len(close_price) if len(close_price) < 100: return print close_price[-10:-1] direction = abs(close_price[-1] - close_price[-10]) volatility = sum(abs(close_price[i+1]-close_price[i]) for i in range(-9,0)) ER = abs(direction/volatility) fastSC = 2.0/(2.0+1) slowSC = 2.0/(30.0+1) sSC = ER * (fastSC-slowSC) + slowSC constaint = sSC*sSC #EMA 100 ema_close_100 = pd.ewma(close_price, span=longDay) ema_high_100 = pd.ewma(high_price, span=longDay) ema_low_100 = pd.ewma(low_price, span=longDay) amaClose = ema_close_100[-1] + constaint * (close_price[-1] - ema_close_100[-1]) amaHigh = ema_high_100[-1] + constaint * (high_price[-1] - ema_high_100[-1]) amaLow = ema_low_100[-1] + constaint * (low_price[-1] - ema_low_100[-1]) print ema_close_100[-1], ema_high_100[-1], ema_low_100[-1] BKPRICE = 0.0 SKPRICE = float('Inf') status = SIGNAL_DEFAULT print high_price[-1], low_price[-1], close_price[-1] if low_price[-1] > amaHigh: status = SIGNAL_BUY elif close_price[-1] < amaClose or close_price[-1] <= 0.995 * BKPRICE: status = SIGNAL_BUY elif high_price[-1] < amaLow: status = SIGNAL_SALE elif close_price[-1] > amaClose or close_price[-1] >= 1.005 * SKPRICE: status = SIGNAL_SALE return status # MA指标择时 (回测) def select_Time_MA(stock_data, stockName): start_money = 100000000 now_count = 0 now_money = start_money # 将数据按照交易日期从远到近排序 stock_data.sort('Date', inplace=True) close_price = stock_data['Adj Close'].get_values() #EMA ma_list = [AVR_SHORT, AVR_LONG] ema_close_short = pd.ewma(close_price, span=ma_list[0]) ema_close_long = pd.ewma(close_price, span=ma_list[1]) signals = [0]*(ma_list[1]+1) tradeTimes = 0 bBuySignal = True for t in range(ma_list[1]+1, len(close_price)): signal = SIGNAL_DEFAULT if ema_close_short[t] > ema_close_short[t-1] and ema_close_short[t] > ema_close_long[t] \ and ema_close_short[t-1] < ema_close_long[t-1]: if bBuySignal: signal = SIGNAL_BUY now_count = (int)(start_money / close_price[t] /100)*100 now_money = start_money - now_count * close_price[t] #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = False elif ema_close_long[t] < ema_close_long[t-1] and ema_close_short[t] < ema_close_long[t] \ and ema_close_short[t-1] > ema_close_long[t-1]: if bBuySignal == False: signal = SIGNAL_SALE now_money += now_count * close_price[t] now_count = 0 #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = True signals.append(signal) if signal != 0: #print 't:', t, ' signal:', signal tradeTimes += 1 print stockName, u"收益率:", (now_money+now_count * close_price[-1]-start_money)/start_money*100, '%\t' \ u"交易次数", tradeTimes, u" 最新市值:", now_money+now_count * close_price[-1] stock_data['SIGNAL_MA'] = signals # fig = plt.figure(facecolor='white') # left, width = 0.1, 0.8 # rect1 = [left, 0.5, width, 0.4] # rect2 = [left, 0.1, width, 0.3] # # axescolor = '#f6f6f6' # the axes background color # ax1 = fig.add_axes(rect1, axisbg=axescolor) #left, bottom, width, height # ax2 = fig.add_axes(rect2, axisbg=axescolor, sharex=ax1) # # ax1.plot(range(len(close_price)), close_price, color="black", linewidth=1) # ax1.grid() # ax2.plot(range(len(ema_close_long)), ema_close_long,label='', color="red", linewidth=1) # ax2.plot(range(len(ema_close_short)), ema_close_short,label='', color="blue", linewidth=1) # ax2.grid() #plt.show() # 将数据按照交易日期从近到远排序 #stock_data.sort('date', ascending=False, inplace=True) # MACD指标择时 (回测) def select_Time_MACD(stock_data, stockName): start_money = 100000000 now_count = 0 now_money = start_money # 将数据按照交易日期从远到近排序 stock_data.sort('Date', inplace=True) close_price = stock_data['Adj Close'].get_values() #EMA ma_list = [AVR_SHORT, AVR_LONG] ma_dea = 10 ema_close_short = pd.ewma(close_price, span=ma_list[0]) ema_close_long = pd.ewma(close_price, span=ma_list[1]) dif_price = ema_close_short - ema_close_long dea_price = pd.ewma(dif_price, span=ma_dea) macd_price = 2 * (dif_price - dea_price) signals = [0]*(ma_list[1]+1) tradeTimes = 0 bBuySignal = True for t in range(ma_list[1]+1, len(close_price)): signal = SIGNAL_DEFAULT if dif_price[t] > dif_price[t-1] and dif_price[t] > dea_price[t] \ and dif_price[t-1] < dea_price[t-1] and dea_price[t] > 0: if bBuySignal: signal = SIGNAL_BUY now_count = (int)(now_money / close_price[t] /100)*100 now_money = start_money - now_count * close_price[t] #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = False elif dif_price[t] < dif_price[t-1] and dif_price[t] < dea_price[t] \ and dif_price[t-1] > dea_price[t-1] and dif_price[t] < 0: if bBuySignal == False: signal = SIGNAL_SALE now_money += now_count * close_price[t] now_count = 0 #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = True signals.append(signal) if signal != 0: #print 't:', t, ' signal:', signal tradeTimes += 1 print stockName, u"收益率:", (now_money+now_count * close_price[-1]-start_money)/start_money*100, '%\t' \ u"交易次数", tradeTimes, u" 最新市值:", now_money+now_count * close_price[-1] stock_data['SIGNAL_MACD'] = signals # fig = plt.figure(facecolor='white') # left, width = 0.1, 0.8 # rect1 = [left, 0.5, width, 0.4] # rect2 = [left, 0.1, width, 0.3] # # axescolor = '#f6f6f6' # the axes background color # ax1 = fig.add_axes(rect1, axisbg=axescolor) #left, bottom, width, height # ax2 = fig.add_axes(rect2, axisbg=axescolor, sharex=ax1) # # ax1.plot(range(len(close_price)), close_price, color="black", linewidth=1) # ax1.grid() # ax2.plot(range(len(dif_price)), ema_close_long,label='', color="red", linewidth=1) # ax2.plot(range(len(dea_price)), ema_close_short,label='', color="blue", linewidth=1) # ax2.grid() #plt.show() # 将数据按照交易日期从近到远排序 #stock_data.sort('date', ascending=False, inplace=True) return dif_price, dea_price, macd_price # DMA指标择时 (回测) def select_Time_DMA(stock_data, stockName): start_money = 100000000 now_count = 0 now_money = start_money # 将数据按照交易日期从远到近排序 stock_data.sort('Date', inplace=True) close_price = stock_data['Adj Close'].get_values() #MA ma_list = [AVR_SHORT, AVR_LONG] ma_dea = 10 ma_close_short = pd.rolling_mean(close_price, ma_list[0]) ma_close_long = pd.rolling_mean(close_price, ma_list[1]) dma_price = ma_close_short - ma_close_long ama_price = pd.rolling_mean(dma_price, ma_dea) signals = [0]*(ma_list[1]+1) tradeTimes = 0 bBuySignal = True for t in range(ma_list[1]+1, len(close_price)): signal = SIGNAL_DEFAULT if dma_price[t] > dma_price[t-1] and dma_price[t] > ama_price[t] \ and dma_price[t-1] < ama_price[t-1]: if bBuySignal: signal = SIGNAL_BUY now_count = (int)(now_money / close_price[t] /100)*100 now_money = start_money - now_count * close_price[t] #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = False elif dma_price[t] < dma_price[t-1] and dma_price[t] < ama_price[t] \ and dma_price[t-1] > ama_price[t-1]: if bBuySignal == False: signal = SIGNAL_SALE now_money += now_count * close_price[t] now_count = 0 #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = True signals.append(signal) if signal != 0: #print 't:', t, ' signal:', signal tradeTimes += 1 print stockName, u"收益率:", (now_money+now_count * close_price[-1]-start_money)/start_money*100, '%\t' \ u"交易次数", tradeTimes, u" 最新市值:", now_money+now_count * close_price[-1] stock_data['SIGNAL_DMA'] = signals # fig = plt.figure(facecolor='white') # left, width = 0.1, 0.8 # rect1 = [left, 0.5, width, 0.4] # rect2 = [left, 0.1, width, 0.3] # # axescolor = '#f6f6f6' # the axes background color # ax1 = fig.add_axes(rect1, axisbg=axescolor) #left, bottom, width, height # ax2 = fig.add_axes(rect2, axisbg=axescolor, sharex=ax1) # # ax1.plot(range(len(close_price)), close_price, color="black", linewidth=1) # ax1.grid() # ax2.plot(range(len(dma_price)), dma_price,label='', color="red", linewidth=1) # ax2.plot(range(len(ama_price)), ama_price,label='', color="blue", linewidth=1) # ax2.grid() #plt.show() # 将数据按照交易日期从近到远排序 #stock_data.sort('date', ascending=False, inplace=True) # DMA指标择时 (回测) def select_Time_TRIX(stock_data, stockName): start_money = 100000000 now_count = 0 now_money = start_money # 将数据按照交易日期从远到近排序 stock_data.sort('Date', inplace=True) close_price = stock_data['Adj Close'].get_values() #EMA ma_list = [AVR_SHORT, AVR_SHORT] #N,M ema_close = pd.ewma(close_price, span=ma_list[0]) ema_close = pd.ewma(ema_close, span=ma_list[0]) tr_close = pd.ewma(ema_close, span=ma_list[0]) trixsList = [0] for i in range(1, len(tr_close)): #print tr_close[i], tr_close[i-1] trix = (tr_close[i]-tr_close[i-1])/tr_close[i-1]*100 trixsList.append(trix) trixs = np.array(trixsList) maxtrix = pd.rolling_mean(trixs, ma_list[1]) signals = [0]*(ma_list[1]+1) tradeTimes = 0 bBuySignal = True for t in range(ma_list[1]+1, len(close_price)): signal = SIGNAL_DEFAULT if trixs[t] > trixs[t-1] and trixs[t] > maxtrix[t] \ and trixs[t-1] < maxtrix[t-1]: if bBuySignal: signal = SIGNAL_BUY now_count = (int)(now_money / close_price[t] /100)*100 now_money = start_money - now_count * close_price[t] #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = False elif trixs[t] < trixs[t-1] and trixs[t] < maxtrix[t] \ and trixs[t-1] > maxtrix[t-1]: if bBuySignal == False: signal = SIGNAL_SALE now_money += now_count * close_price[t] now_count = 0 #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = True signals.append(signal) if signal != 0: #print 't:', t, ' signal:', signal tradeTimes += 1 print stockName, u"收益率:", (now_money+now_count * close_price[-1]-start_money)/start_money*100, '%\t' \ u"交易次数", tradeTimes, u" 最新市值:", now_money+now_count * close_price[-1] stock_data['SIGNAL_TRIX'] = signals # 组合择时指标 (回测) def select_Time_Mix(stock_data, stockName): start_money = 100000000 now_count = 0 now_money = start_money # 综合策略 signals = [] tradeTimes = 0 bBuySignal = True close_price = stock_data['Adj Close'].get_values() s_ma = stock_data['SIGNAL_MA'].get_values() s_macd = stock_data['SIGNAL_MACD'].get_values() s_dma = stock_data['SIGNAL_DMA'].get_values() s_trix = stock_data['SIGNAL_TRIX'].get_values() for i in range(len(s_ma)): signal = SIGNAL_DEFAULT up = 0; down = 0; if s_ma[i] == 1: up += 1 elif s_ma[i] == -1: down += 1 if s_macd[i] == 1: up += 1 elif s_macd[i] == -1: down += 1 if s_dma[i] == 1: up += 1 elif s_dma[i] == -1: down += 1 if s_trix[i] == 1: up += 1 elif s_trix[i] == -1: down += 1 if up >= 3: if bBuySignal: signal = SIGNAL_BUY now_count = (int)(now_money / close_price[i] /100)*100 now_money = start_money - now_count * close_price[i] #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = False elif down <= -3: if bBuySignal == False: signal = SIGNAL_SALE now_money += now_count * close_price[i] now_count = 0 #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money bBuySignal = True signals.append(signal) if signal != 0: #print 't:', t, ' signal:', signal tradeTimes += 1 print stockName, u"收益率:", (now_money+now_count * close_price[-1]-start_money)/start_money*100, '%\t' \ u"交易次数", tradeTimes, u" 最新市值:", now_money+now_count * close_price[-1] stock_data['SIGNAL_MIX'] = signals # AMA指标择时 def select_Time_AMA(stock_data, stockName): percentage = 0.1 start_money = 100000000 now_count = 0 now_money = 0 one_hand = 10000 # 将数据按照交易日期从远到近排序 stock_data.sort('Date', inplace=True) close_price = stock_data['Adj Close'].get_values() # 指数平滑序列 containts = [0]*10 for i in range(10, len(close_price)): sub_price = close_price[i-10:i] constaint = getConstaint(sub_price) containts.append(constaint); ama_price = [close_price[0]] for i in range(1, len(close_price)): ama = containts[i-1] * close_price[i-1] + (1-containts[i-1])*ama_price[i-1] ama_price.append(ama) signals = [0]*21 tradeTimes = 0 record_buy = 0 record_sale = [] # 从20天以后开始判断买卖点 for i in range(21, len(ama_price)): signal = SIGNAL_DEFAULT #print np.array(ama_price[i-19:i+1]) - np.array(ama_price[i-20:i]) threshold = percentage * np.std(np.array(ama_price[i-19:i+1]) - np.array(ama_price[i-20:i])) # 过滤器 if ama_price[i] - np.min(ama_price[i-5:i]) > threshold: signal = SIGNAL_BUY now_count += one_hand record_buy += one_hand * close_price[i] #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money elif np.max(ama_price[i-5:i]) - ama_price[i] > threshold: signal = SIGNAL_SALE if now_count > one_hand: now_count -= one_hand record_sale = one_hand * close_price[i] #print u"股票价格/持股数/剩余金额:",close_price[t], '/', now_count, '/', now_money signals.append(signal) if signal != 0: #print 't:', t, ' signal:', signal tradeTimes += 1 # 成本 print u'盈利', record_sale + now_count * close_price[-1] - record_buy # print stockName, u"收益率:", (now_money+now_count * close_price[-1]-start_money)/start_money*100, '%\t' \ # u"交易次数", tradeTimes, u" 最新市值:", now_money+now_count * close_price[-1] stock_data['SIGNAL_AMA'] = signals return ama_price # 获取平方平滑系数 def getConstaint(prices): direction = abs(prices[-1] - prices[0]) volatility = sum(abs(prices[i+1]-prices[i]) for i in range(len(prices)-1)) ER = abs(direction/volatility) fastSC = 2.0/(2.0+1) slowSC = 2.0/(30.0+1) sSC = ER * (fastSC-slowSC) + slowSC constaint = sSC*sSC return constaint # 选择一种均线策略 def getMAStrategy(stockCsvPath, stockName, strategyName='MACD'): if os.path.exists(stockCsvPath) == False: return stock_data = pd.read_csv(stockCsvPath) if strategyName == 'MACD': return select_Time_MACD(stock_data, stockName) elif strategyName == 'MA': return select_Time_MA(stock_data, stockName) elif strategyName == 'DMA': return select_Time_DMA(stock_data, stockName) elif strategyName == 'TRIX': return select_Time_TRIX(stock_data, stockName) elif strategyName == 'AMA': return select_Time_AMA(stock_data, stockName) # 执行策略 def run(stockCsvPath, stockName): if os.path.exists(stockCsvPath) == False: return #stockCsvNewPath = stockName + '_macd.csv' #processEMA(stockCsvPath, stockCsvNewPath) stock_data = pd.read_csv(stockCsvPath) #self_adaptive_ma(stock_data) print u'>>>>>>>>>>>>> MA 策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_MA(stock_data, stockName) print u'>>>>>>>>>>>>> MACD 策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_MACD(stock_data, stockName) print u'>>>>>>>>>>>>> DMA 策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_DMA(stock_data, stockName) print u'>>>>>>>>>>>>> TRIX 策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_TRIX(stock_data, stockName) print u'>>>>>>>>>>>>> 组合策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_Mix(stock_data, stockName) print u'>>>>>>>>>>>>> AMA策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_AMA(stock_data, stockName) print '\n' if __name__ == "__main__": print "main begin" stockList=['000725','000783','002167','002505','002600','300315','600000','600011','600048','601001'] #stockList = ['000725'] for stockName in stockList: # if stockName != '002600': # continue stockCsvPath = os.path.pardir +"\\stockdata\\" + stockName + '.csv' #stockCsvPath = stockName + '.csv' if os.path.exists(stockCsvPath) == False: continue #stockCsvNewPath = stockName + '_macd.csv' #processEMA(stockCsvPath, stockCsvNewPath) stock_data = pd.read_csv(stockCsvPath) #self_adaptive_ma(stock_data) print u'>>>>>>>>>>>>> MA 策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_MA(stock_data, stockName) print u'>>>>>>>>>>>>> MACD 策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_MACD(stock_data, stockName) print u'>>>>>>>>>>>>> DMA 策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_DMA(stock_data, stockName) print u'>>>>>>>>>>>>> TRIX 策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_TRIX(stock_data, stockName) print u'>>>>>>>>>>>>> 组合策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_Mix(stock_data, stockName) print u'>>>>>>>>>>>>> AMA策略 >>>>>>>>>>>>>>>>>>>>>>>>>>' select_Time_AMA(stock_data, stockName) print '\n' print "main end"