一個小技巧,VNPY策略引數優化時候顯示完成數量和總數量

張國平發表於2020-09-11

在做VNPY 策略引數優化的時候, 優化數量多的時候要好幾天,有時候也不知道完成數量,只能乾等。就稍微改了下程式碼,加入log顯示完成數量和總數量,心裡面有個底。


程式碼是在VNPY 1.9.2裡面的因為我還在1.9.2的版本泥潭裡,2.0之後直接用應該也可以的,只要稍微改下變數名稱。


實質內容,就是python多程式共享變數訪問更新,python提供幾個不同的多程式變數共享的方法,比如使用可變物件queue。這裡其實只用定義一個int型別的counter,每個程式跑完後,counter加一,並在log中記錄。

這裡用了一個multiprocessing.Manager類,Manager可以對定義共享變數,和鎖管理


把下面程式碼加入到class BacktestingEngine的runParallelOptimization方法中

#----------------------------------------------------------------------
def runParallelOptimization(self, strategyClass, optimizationSetting):
    """並行優化引數"""
    # 獲取優化設定
    settingList = optimizationSetting.generateSetting()
    targetName = optimizationSetting.optimizeTarget
    # 檢查引數設定問題
    if not settingList or not targetName:
        self.output(u'優化設定有問題,請檢查')
    # 多程式優化,啟動一個對應CPU核心數量的程式池
    pool = multiprocessing.Pool(multiprocessing.cpu_count()-1, maxtasksperchild = 10)
    l = []
    length0 = len(settingList)  # 獲得引數優化帶執行條
    manger =  multiprocessing.Manager() # 定義一個多程式管理物件
    counter = manger.Value('i',0) # 定義一個共享變數記錄完成條目,int型別的
    lock = manger.Lock() # 頂一個訪問鎖,如果counter被一個程式修改時候,加鎖,
    for setting in settingList:
        # 把剛剛頂一個的作為引數傳入每個程式,實現變數共享
        l.append(pool.apply_async(optimize, (strategyClass, setting,
                                             targetName, self.mode,
                                             self.startDate, self.initDays, self.endDate,
                                             self.slippage, self.rate, self.size, self.priceTick,
                                             self.dbName, self.symbol,counter,lock,length0))) 
    pool.close()
    pool.join()
    # 顯示結果
    resultList = [res.get() for res in l]
    resultList.sort(reverse=True, key=lambda result:result[1])
    return resultList


然後在optimize中,定義counter加1

#----------------------------------------------------------------------
def optimize(strategyClass, setting, targetName,
             mode, startDate, initDays, endDate,
             slippage, rate, size, priceTick,
             dbName, symbol,counter,lock,length0):
    """多程式優化時跑在每個程式中執行的函式"""
    ......
    engine.runBacktesting()
    # 當優化完成時候,counter加1
    with lock:
        counter.value += 1
    # 為了使用engine的log顯示,更改calculateDailyResult,傳入counter.value, length0
    engine.calculateDailyResult(counter.value, length0)
    
    .....


為了在log中顯示,不得不修改下calculateDailyResult,其實這樣改原始碼不太合適,反正1.9.2已經被我搞得亂了,僅作參考,不合適的更新方法。

#----------------------------------------------------------------------
def calculateDailyResult(self,count = 0,length0 = 0):
    """計算按日統計的交易結果"""
    self.output(u'計算按日統計結果')
    # 顯示完成數
    if count != 0:
        self.output(u'執行完成個數 %s / %s' % (count,length0))
    ......


實現效果如下圖,可以預估之後還有多少要完成。

當然有心可以加一個共享變數,記錄下已經 每次更新間隔時間,乘上未完成個數,估算出還有多少時間才完成。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22259926/viewspace-2718790/,如需轉載,請註明出處,否則將追究法律責任。

相關文章