寫了一個類GeneticOptimizeStrategy,針對VNPY策略遺傳演算法優化
寫了一個類,GeneticOptimizeStrategy,
- Parameterlist 字典; 簡化了呼叫引數和定義對應隨機範圍問題。只要在Parameterlist 中定義策略引數名稱和對應的隨機範圍就可以,其中兩個引數的元祖是兩個之間隨機數,呼叫random.uniform(),三個引數元祖是開始結束和中間步進,呼叫的是random.randrange(), 如果是陣列就是在陣列中間隨機選擇。
- Symbollist 字典,維護回測品種和資料
-
poptoExcel方法,輸出一個Excel,包括引數和value;引數可以直接呼叫。同時把相同項合併。效果如下圖
原始碼也可以去我的GitHub中
-------------------------------------------------------------------------------------------------------------
發現多執行緒時候有報錯
cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup
builtin
.instanceme
搜尋一下,發現是python2.7多程式問題,pool.map沒法繫結包在類裡面方法。
把evaluate的方法放在類外面做成靜態方法繫結,雖然解決了pickle,但是在多執行緒情況下,策略引數名字和值的對應經出出錯。
就把引數賦值的方式也改了,從
[value1,value2,value3...]變成[{key1:value1},{key2,value2},{key3,value3}...],這樣。可以滿足交叉,突變要求。生成隨機DNA演算法要改下。
def parameter_generate(self): ''' 根據設定的起始值,終止值和步進,隨機生成待優化的策略引數 ''' parameter_list = [] for key, value in self.parameterlist.items(): if isinstance(value, tuple): if len(value) == 3: parameter_list.append({key:random.randrange(value[0], value[1], value[2])}) elif len(value) == 2: parameter_list.append({key:random.uniform(value[0], value[1])}) elif isinstance(value, list): parameter_list.append({key:random.choice(value)}) else: parameter_list.append({key:value}) return parameter_list
parameter_list是類似vnpy optimize的格式,不過有所增強。 strategy_avg返回變成了[{key1:value1},{key2,value2},{key3,value3}...],包含字典的list格式也可以滿足交叉和突變方法。
在進化篩選方法object_func,使用下面遍歷把[{key1:value1},{key2,value2},{key3,value3}...]變回{key1,value1,key2,value2...},這樣就可以進入回測
setting = {} for item in range(len(strategy_avg)): setting.update(strategy_avg[item])
最後,因為進化篩選方法object_func放在類外面,但必須要把一些回測引數,比如品種,日期等的傳入,這裡有兩種方式可以實現,一個是把傳入individual list改為Tuple list,變成[(individual, parameterPackage)..]這樣list,但是就要修改algorithms.eaMuPlusLambda,比較麻煩。
還有一個是增強individual, 加入這個回測引數集做為屬性。但是多執行緒也有些要注意,不得不把parameterPackage做為靜態屬性放在類裡面,不然回提示parameterPackage為空。還沒有找到比較合適處理方法
creator.create("Individual", list, fitness=creator.FitnessMulti, parameterPackage=parameterPackage)
完整新程式碼如下
# encoding: UTF-8 """ 展示如何執行引數優化。 """ from __future__ import division from __future__ import print_function from vnpy.trader.app.ctaStrategy.ctaBacktesting import BacktestingEngine, MINUTE_DB_NAME, OptimizationSetting from vnpy.trader.app.ctaStrategy.strategy.strategyBollChannel import BollChannelStrategy import random import numpy as np from deap import creator, base, tools, algorithms import multiprocessing import time, datetime import pandas as pd def object_func(strategy_avgTuple): """ 本函式為優化目標函式,根據隨機生成的策略引數,執行回測後自動返回2個結果指標:收益回撤比和夏普比率 """ strategy_avg = strategy_avgTuple paraSet = strategy_avgTuple.parameterPackage symbol = paraSet["symbol"] strategy = paraSet["strategy"] # 建立回測引擎物件 engine = BacktestingEngine() # 設定回測使用的資料 engine.setBacktestingMode(engine.BAR_MODE) # 設定引擎的回測模式為K線 engine.setDatabase("VnTrader_1Min_Db", symbol["vtSymbol"]) # 設定使用的歷史資料庫 engine.setStartDate(symbol["StartDate"]) # 設定回測用的資料起始日期 engine.setEndDate(symbol["EndDate"]) # 設定回測用的資料起始日期 # 配置回測引擎引數 engine.setSlippage(symbol["Slippage"]) # 1跳 engine.setRate(symbol["Rate"]) # 佣金大小 engine.setSize(symbol["Size"]) # 合約大小 engine.setPriceTick(symbol["Slippage"]) # 最小价格變動 engine.setCapital(symbol["Capital"]) setting = {} for item in range(len(strategy_avg)): setting.update(strategy_avg[item]) engine.clearBacktestingResult() # 載入策略 engine.initStrategy(strategy, setting) # 執行回測,返回指定的結果指標 engine.runBacktesting() # 執行回測 # 逐日回測 # engine.calculateDailyResult() backresult = engine.calculateBacktestingResult() try: capital = round(backresult['capital'], 3) # 收益回撤比 profitLossRatio = round(backresult['profitLossRatio'], 3) # 夏普比率 #夏普比率 sharpeRatio = round(backresult['sharpeRatio'], 3) except Exception, e: print("Error: %s, %s" %(str(Exception),str(e))) sharpeRatio = 0 profitLossRatio = 0 # 收益回撤比 averageWinning = 0 # 夏普比率 #夏普比率 capital = 0 return capital, sharpeRatio, profitLossRatio class GeneticOptimizeStrategy(object): Strategy = BollChannelStrategy Symbollist ={ "vtSymbol": 'rb0000', "StartDate": "20140601", "EndDate": "20141101", "Slippage": 1, "Size": 10, "Rate": 2 / 10000.0, "Capital": 10000 } Parameterlist = { 'bollWindow': (10,50,1), #布林帶視窗 'bollDev': (2,10,1), #布林帶通道閾值 'slMultiplier':(3,6), 'barMins':[2,3,5,10,15,20], } parameterPackage = { "symbol":Symbollist, "strategy":Strategy } # ------------------------------------------------------------------------ def __init__(self, Strategy, Symbollist, Parameterlist): self.strategy = Strategy self.symbol = Symbollist self.parameterlist = Parameterlist self.parameterPackage = { "strategy":self.strategy, "symbol":self.symbol } creator.create("FitnessMulti", base.Fitness, weights=(1.0, 1.0, 1.0)) # 1.0 求最大值;-1.0 求最小值 creator.create("Individual", list, fitness=creator.FitnessMulti, parameterPackage=parameterPackage) # ------------------------------------------------------------------------ def parameter_generate(self): ''' 根據設定的起始值,終止值和步進,隨機生成待優化的策略引數 ''' parameter_list = [] for key, value in self.parameterlist.items(): if isinstance(value, tuple): if len(value) == 3: parameter_list.append({key:random.randrange(value[0], value[1], value[2])}) elif len(value) == 2: parameter_list.append({key:random.uniform(value[0], value[1])}) elif isinstance(value, list): parameter_list.append({key:random.choice(value)}) else: parameter_list.append({key:value}) return parameter_list def mutArrayGroup(self, individual, parameterlist, indpb): size = len(individual) paralist = parameterlist() for i in xrange(size): if random.random() < indpb: individual[i] = paralist[i] return individual, def optimize(self): # 設定優化方向:最大化收益回撤比,最大化夏普比率 toolbox = base.Toolbox() # Toolbox是deap庫內建的工具箱,裡面包含遺傳演算法中所用到的各種函式 pool = multiprocessing.Pool(processes=(multiprocessing.cpu_count()-1)) toolbox.register("map", pool.map) # 初始化 toolbox.register("individual", tools.initIterate, creator.Individual, self.parameter_generate) # 註冊個體:隨機生成的策略引數parameter_generate() toolbox.register("population", tools.initRepeat, list, toolbox.individual) # 註冊種群:個體形成種群 toolbox.register("mate", tools.cxTwoPoint) # 註冊交叉:兩點交叉 toolbox.register("mutate", self.mutArrayGroup, parameterlist=self.parameter_generate, indpb=0.6) # 註冊變異:隨機生成一定區間內的整數 toolbox.register("evaluate", object_func) # 註冊評估:優化目標函式object_func() toolbox.register("select", tools.selNSGA2) # 註冊選擇:NSGA-II(帶精英策略的非支配排序的遺傳演算法) # 遺傳演算法引數設定 MU = 8 # 設定每一代選擇的個體數 LAMBDA = 5 # 設定每一代產生的子女數 pop = toolbox.population(20) # 設定族群裡面的個體數量 CXPB, MUTPB, NGEN = 0.5, 0.3, 10 # 分別為種群內部個體的交叉概率、變異概率、產生種群代數 hof = tools.ParetoFront() # 解的集合:帕累託前沿(非佔優最優集) # 解的集合的描述統計資訊 # 集合內平均值,標準差,最小值,最大值可以體現集合的收斂程度 # 收斂程度低可以增加演算法的迭代次數 stats = tools.Statistics(lambda ind: ind.fitness.values) np.set_printoptions(suppress=True) # 對numpy預設輸出的科學計數法轉換 stats.register("mean", np.mean, axis=0) # 統計目標優化函式結果的平均值 stats.register("std", np.std, axis=0) # 統計目標優化函式結果的標準差 stats.register("min", np.min, axis=0) # 統計目標優化函式結果的最小值 stats.register("max", np.max, axis=0) # 統計目標優化函式結果的最大值 # 執行演算法 algorithms.eaMuPlusLambda(pop, toolbox, MU, LAMBDA, CXPB, MUTPB, NGEN, stats, halloffame=hof, verbose=True) # esMuPlusLambda是一種基於(μ+λ)選擇策略的多目標優化分段遺傳演算法 return pop def poptoExcel(self, pop, number = 1000, path = "C:/data/"): #按照輸入統計資料佇列和路徑,輸出excel,這裡不提供新增模式,如果想,可以改 #dft.to_csv(path,index=False,header=True, mode = 'a') path = path + self.strategy.className + "_" + self.symbol[ "vtSymbol"] + str(datetime.date.today())+ ".xls" summayKey = ["StrategyParameter","TestValues"] best_ind = tools.selBest(pop, number) dft = pd.DataFrame(columns=summayKey) for i in range(0,len(best_ind)-1): if i == 0: # new = pd.DataFrame([{"StrategyParameter":self.complieString(best_ind[i])},{"TestValues":best_ind[i].fitness.values}], index=["0"]) dft = dft.append([{"StrategyParameter":self.complieString(best_ind[i]),"TestValues":best_ind[i].fitness.values}], ignore_index=True) elif str(best_ind[i-1]) == (str(best_ind[i])): pass else: #new = pd.DataFrame({"StrategyParameter":self.complieString(best_ind[i]),"TestValues":best_ind[i].fitness.values}, index=["0"]) dft = dft.append([{"StrategyParameter":self.complieString(best_ind[i]),"TestValues":best_ind[i].fitness.values}], ignore_index=True) dft.to_excel(path,index=False,header=True) print("回測統計結果輸出到" + path) def complieString(self,individual): setting = {} for item in range(len(individual)): setting.update(individual[item]) return str(setting) if __name__ == "__main__": Strategy = BollChannelStrategy Symbollist ={ "vtSymbol": 'rb0000', "StartDate": "20140601", "EndDate": "20141101", "Slippage": 1, "Size": 10, "Rate": 2 / 10000.0, "Capital": 10000 } Parameterlist = { 'bollWindow': (10,50,1), #布林帶視窗 'bollDev': (2,10,1), #布林帶通道閾值 'slMultiplier':(3,6), 'barMins':[2,3,5,10,15,20], } parameterPackage = { "symbol":Symbollist, "parameterlist":Parameterlist, "strategy":Strategy } GE = GeneticOptimizeStrategy(Strategy,Symbollist,Parameterlist) GE.poptoExcel(GE.optimize()) print("-- End of (successful) evolution --")
-------------------------------------------------------------------------------------------------------------
https://github.com/BillyZhangGuoping/MarketDataAnaylzerbyDataFrame/tree/master/GeneticOptimizeforVNPYStrategy
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22259926/viewspace-2640851/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 利用遺傳演算法庫DEAP優化交易策略演算法優化
- 【智慧優化演算法】遺傳演算法的精英選擇策略、期望選擇策略優化演算法
- 利用粒子群優化演算法(PSO)來優化vnpy的量化策略引數優化演算法
- 【多目標優化演算法】非支配的精英策略遺傳演算法:NSGA-II優化演算法
- 一個小技巧,VNPY策略引數優化時候顯示完成數量和總數量優化
- 遺傳演算法(一):Basic GA演算法
- 【redis前傳】自己手寫一個LRU策略 | redis淘汰策略Redis
- 智慧優化演算法——python實現免疫遺傳演算法的影像擬合優化演算法Python
- 遺傳演算法演算法
- 從遺傳演算法到OpenAI新方向:進化策略工作機制全解演算法OpenAI
- 透過MATLAB分別對比二進位制編碼遺傳最佳化演算法和實數編碼遺傳最佳化演算法Matlab演算法
- MySQL 針對 like 條件的優化MySql優化
- Python遺傳演算法工具箱的使用(一)求解帶約束的單目標優化Python演算法優化
- 針對vnpy的不同期貨品種行情資料清理
- 使用MPI並行化遺傳演算法框架GAFT並行演算法框架
- Python遺傳演算法框架使用例項(二)多目標優化問題Geatpy for Python與Matlab的對比學習Python演算法框架優化Matlab
- 遺傳演算法的基本框架演算法框架
- python遺傳演算法(詳解)Python演算法
- 寫了一個 SRE 除錯工具,類似一個小木馬除錯
- MATLAB實戰系列(十一)-多種群遺傳演算法的函式優化演算法(附MATLAB程式碼)Matlab演算法函式優化
- 遺傳演算法解決函式最佳化問題演算法函式
- 針對雲原生轉型的6個關鍵資料策略
- mysql之 CentOS系統針對mysql引數優化MySqlCentOS優化
- 如何針對SEO優化您的WordPress Robots.txt優化
- VNPY 批量優化引數,並輸出到excel優化Excel
- 10分鐘搞懂遺傳演算法演算法
- 人工智慧 (13) 遺傳演算法人工智慧演算法
- 如何學習python遺傳演算法?Python演算法
- 針對vnpy的mongodb資料庫,合併多個主力合約行情為連續行情資料MongoDB資料庫
- 遺傳演算法組卷使用心得演算法
- 遺傳演算法詳解與實驗演算法
- 遺傳演算法解決TSP問題演算法
- 寫了一個 WebSocket 框架Web框架
- 寫了一個 MySQL 代理MySql
- 基於JDBC寫一個和mybatis類似的對映框架—DBUtilsJDBCMyBatis框架
- 粒子群演算法和遺傳演算法的比較演算法
- “我被HR針對了”,應屆生簡歷千萬別這麼寫
- SQL優化這麼做就對了SQL優化