利用VNPY回測引擎分析實盤交易,並用excel和pdf輸出分析結果
算是之前一篇文章的後續
http://blog.itpub.net/22259926/viewspace-2564798/
之前寫了一篇文章,在實盤交易時候,用資料庫記錄交易資訊,其實就是把交易資訊型別VtTradeData的例項儲存的到資料庫中。
之前盤後分析主要是資料庫把collection匯出到csv文件,然後下載本地用excel分析,拼湊出sharpe指標,趨勢圖一些;費時費力還不準確;只能說近似正確。
一直想找個什麼分析工具,後來一想,其實VNPY回測引擎就很不錯,簡單易用;就是搗鼓搗鼓,利用VNPY回測引擎分析實盤交易,並用excel和pdf輸出分析結果。
這裡所有程式碼還是針對VNPY 1.92的,因為現在我的實盤還是這個版本,如果VNPY2的版本,其實應該改改也可以用。
完整程式碼如下,只要儲存到一個本地路徑,執行就可以。
整個流程是:
1. 使用方法load_tradedata,傳入交易記錄資料庫資訊,和collection名稱,讀取交易資訊,儲存為OrderDict格式
2. 使用initEngine4Deal,初始化一個回測引擎,傳入品種交易引數,比如手續費一類,進行更完善計算,滑點可以為0,因為是真實成交資料; 這裡還要提供歷史品種行情資料,為按日結算提供參考;同時使用真實歷史交易資訊Dict,替換本來是回測生成的交易資訊tradeDict,這個也是核心步驟。
3.然後用回測引擎的按比分析方法,和按日分析方法分析;把分析結果用Dict儲存;轉為excel輸出;影像plt用pdf輸出。這裡有箇中文亂碼問題,比較討厭,可以搜尋看看解決方法。
完成後截圖下如,
Excel做了行列轉換,方便檢視
大部分註釋都解釋了。有幾點要介紹下,程式碼如下:
傳入的是用list包Dict的格式,大部分都註釋解釋了。
# encoding: UTF-8 """ 從DEAL資料庫中讀取交易記錄,利用回測分析引擎分析,並用excel和pdf輸出分析結果 """ from __future__ import division from __future__ import print_function from vnpy.trader.app.ctaStrategy.ctaBacktesting import BacktestingEngine, MINUTE_DB_NAME from vnpy.trader.vtObject import VtTickData, VtBarData from vnpy.trader.vtGateway import VtTradeData from vnpy.trader.vtGlobal import globalSetting import pymongo from collections import OrderedDict from datetime import datetime,date import pandas as pd import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_pdf import PdfPages def load_tradedata(dbName, collectionName, startDate): """ 讀取交易歷史記錄,返回用OrderedDict儲存的VtTradeData :param dbName: :param collectionName: :return: {ID:VtTradeData} """ dbClient = pymongo.MongoClient(globalSetting['mongoHost'], globalSetting['mongoPort']) collection = dbClient[dbName][collectionName] # 載入初始化需要用的資料 flt = {} initCursor = collection.find(flt).sort('tradeTime') tradeDict = OrderedDict() # 交易記錄字典 tradeDictID = 0 # 交易編號 for d in initCursor: trade = VtTradeData() trade.__dict__ = d trade.tradeTime = datetime.strptime(trade.tradeTime, '%Y-%m-%d %H:%M:%S') trade.dt = trade.tradeTime tradeDictID += 1 # 成交編號自增1 tradeDict[str(tradeDictID)] = trade return tradeDict def initEngine4Deal(dealCollection,historyCollection,startDate,tradeRate,tradeSize,tradePriceTick,tradeSlipe = 0, tradeCapital = 50000): """ 傳入引數,返回回測引擎,保護實際交易資料,用來分析交易情況,。 :param dealCollection: :param historyCollection: :param startDate: :param tradeSlipe: :param tradeRate: :param tradeSize: :param tradePriceTick: :param tradeCapital: :param exportPDF: :return: """ # 建立回測引擎物件 engine = BacktestingEngine() # 設定回測使用的資料 engine.setBacktestingMode(engine.BAR_MODE) # 設定引擎的回測模式為K線 engine.setDatabase(MINUTE_DB_NAME, historyCollection) # 設定使用的歷史資料庫 engine.setStartDate(startDate) # 設定回測用的資料起始日期 # 配置回測引擎引數 engine.setSlippage(tradeSlipe) # 設定滑點為1跳 engine.setRate(tradeRate) # 設定手續費萬1 engine.setSize(tradeSize) # 設定合約大小 engine.setPriceTick(tradePriceTick) # 設定最小价格變動 engine.setCapital(tradeCapital) # 設定回測本金 engine.loadHistoryData() bar = None for d in engine.dbCursor: data = VtBarData() data.__dict__ = d engine.updateDailyClose(data.datetime, data.close) bar = data # # 構建每日收盤價 # for bar in engine.BackTestData: # engine.updateDailyClose(bar.datetime, bar.close) # 是回測資料後一個bar,用於未結束持倉計算收益 engine.bar = bar # 讀取歷史交易資料,塞入回測引擎 tradeDict = load_tradedata("VnTrader_DEAL_Db",dealCollection,startDate) engine.tradeDict = tradeDict # 顯示成交記錄 # for i in range(len(tradeDict)): # d = engine.tradeDict[str(i + 1)].__dict__ # print('TradeID: %s, Time: %s, Direction: %s, Price: %s, Volume: %s' % ( # d['tradeID'], d['dt'], d['direction'], d['price'], d['volume'])) return engine def tradeResultAnalysis(engine,dealCollection): """ 傳入回測引擎,和deal名稱,按deal進行回測分析,返回回測分析結果DICT格式,和plt圖示用於pdf輸出 :param engine: :param dealCollection: :return: """ TradeResult = {} d = engine.calculateBacktestingResult() TradeResult[u"第一筆交易/FirstDeal"] = d['timeList'][0] TradeResult[u"最後一筆交易/LastDeal"] = d['timeList'][-1] TradeResult[u"總交易次數/DealNumber"] = (d['totalResult']) TradeResult[u"總盈虧/DealPnL"] = (d['capital']) TradeResult[u"最大回撤/MaxDrawdown"] = (min(d['drawdownList'])) TradeResult[u"平均每筆盈利/AveragePnL"] = (d['capital'] / d['totalResult']) TradeResult[u"平均每筆滑點/AverageSlip"] = (d['totalSlippage'] / d['totalResult']) TradeResult[u"平均每筆佣金/AverageCommisson"] = (d['totalCommission'] / d['totalResult']) TradeResult[u"勝率/WinRate%"] =(d['winningRate']) TradeResult[u"盈利交易平均值/AverageProfit"] = (d['averageWinning']) TradeResult[u"虧損交易平均值/AverageLoss"] = (d['averageLosing']) TradeResult[u"盈虧比/ProfitLossRatio"] = (d['profitLossRatio']) plt = tradeResult2Plt(d,TradeResult,dealCollection) return TradeResult, plt def dailyResultAnalysis(engine, dealCollection): """ 傳入回測引擎,和deal名稱,按每日進行回測分析,返回回測分析結果DICT格式,和plt圖示用於pdf輸出 :param engine: :param dealCollection: :return: """ engine.calculateDailyResult() dx, dailyResult = engine.calculateDailyStatistics() plt = dailyResult2Plt(dx, dailyResult, dealCollection) return dailyResult,plt def tradeResult2Plt(d,TradeResult,dealCollection): # 輸出按交易統計 plt 圖示 # 繪圖 fig = plt.figure(figsize=(10, 18)) pText = plt.subplot(5, 1, 1) pText.set_title("TradeResultAnalysis " + dealCollection) pText.text(0,0.1,str(TradeResult),fontsize=12, bbox={'facecolor':'white'},wrap=True) pCapital = plt.subplot(5, 1, 2) pCapital.set_ylabel("capital") pCapital.plot(d['capitalList'], color='r', lw=0.8) pDD = plt.subplot(5, 1, 3) pDD.set_ylabel("DD") pDD.bar(range(len(d['drawdownList'])), d['drawdownList'], color='g') pPnl = plt.subplot(5, 1, 4) pPnl.set_ylabel("pnl") pPnl.hist(d['pnlList'], bins=50, color='c') pPos = plt.subplot(5, 1, 5) pPos.set_ylabel("Position") if d['posList'][-1] == 0: del d['posList'][-1] tradeTimeIndex = [item.strftime("%m/%d %H:%M:%S") for item in d['tradeTimeList']] xindex = np.arange(0, len(tradeTimeIndex), np.int(len(tradeTimeIndex) / 10)) tradeTimeIndex = list(map(lambda i: tradeTimeIndex[i], xindex)) pPos.plot(d['posList'], color='k', drawstyle='steps-pre') pPos.set_ylim(-1.2, 1.2) plt.sca(pPos) # plt.rcParams['font.sans-serif'] = ['SimSun'] # 用來正常顯示中文標籤 plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號 plt.tight_layout() plt.xticks(xindex, tradeTimeIndex, rotation=30) # 旋轉15 return plt def dailyResult2Plt(d, dailyResult,dealCollection): # 繪圖 fig = plt.figure(figsize=(10, 18)) pText = plt.subplot(5, 1, 1) pText.set_title("DailyResultAnalysis " + dealCollection) pText.text(0,0.1,str(dailyResult),fontsize=12 , bbox={'facecolor':'white'},wrap=True) pBalance = plt.subplot(5, 1, 2) pBalance.set_title('Balance') plt.plot(d['date'], d['balance']) pDrawdown = plt.subplot(5, 1, 3) pDrawdown.set_title('Drawdown') pDrawdown.fill_between(range(len(d['drawdown'])), d['drawdown']) pPnl = plt.subplot(5, 1, 4) pPnl.set_title('Daily Pnl') plt.bar(range(len(d['drawdown'])), d['netPnl']) pKDE = plt.subplot(5, 1, 5) pKDE.set_title('Daily Pnl Distribution') plt.hist(d['netPnl'], bins=50) return plt def toExcel(resultlist, path="C:\data\datframe.xlsx"): # 按照輸入統計資料佇列和路徑,輸出excel,這裡不提供新增模式,如果想,可以改 # dft.to_csv(path,index=False,header=True, mode = 'a') summayKey = resultlist[0].keys() df = pd.DataFrame(columns=summayKey) for result in resultlist: new = pd.DataFrame(result, index=["0"]) df = df.append(new, ignore_index=True,sort=True) dft = pd.DataFrame(df.values.T, index=df.columns, columns=df["DealCollection"]) dft.to_excel(path, index=True, header=True) print("回測統計結果輸出到" + path) if __name__ == "__main__": DealCollectionList = [ { "historyCollection": "rb9999", "dealCollection": "ATRStrategy RB", "StartDate": "20200301", "Size": 10, "Rate": 0.0001, "PriceTick":1 }, { "historyCollection": "fu8888", "dealCollection": "CCIStrategy fu", "StartDate": "20200301", "Size": 10, "Rate": 0.0001, "PriceTick": 1 }, ] resultList = [] pdf = PdfPages("DealResultAnalysisPDF" + str(date.today())+ "v1.pdf") for dealCollction in DealCollectionList: ResultDict = {} # 加入交易集名稱 dealCollctionName = dealCollction["dealCollection"] ResultDict["DealCollection"] = dealCollctionName # 初始回測引擎 engine = initEngine4Deal( dealCollection = dealCollction["dealCollection"], historyCollection = dealCollction["historyCollection"], startDate = dealCollction["StartDate"], tradeSize = dealCollction["Size"], tradeRate = dealCollction["Rate"], tradePriceTick = dealCollction["PriceTick"] ) # 按deal進行分析,傳入resultDict,和pdf tradeResult,plt=tradeResultAnalysis(engine,dealCollctionName) ResultDict.update(tradeResult) pdf.savefig() plt.close() # 按每日進行分析,傳入resultDict,和pdf dailyResult,plt= dailyResultAnalysis(engine,dealCollctionName) ResultDict.update(dailyResult) pdf.savefig() plt.close() resultList.append(ResultDict) pdf.close() path = "DealResultAnalysisExcel" + str(date.today()) + "v2.xls" toExcel(resultList, path)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22259926/viewspace-2700573/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- VNPY 批量策略回測和統計結果的excel輸出Excel
- VNPY 批量優化引數,並輸出到excel優化Excel
- 壓測結果分析
- 如何利用NLog輸出結構化日誌,並在Kibana優雅分析日誌?
- VNPY實盤交易中,出現發單成功但是沒有交易情況
- 利用儲存的成交訂單,生成實盤交易分析報表
- VNPY 交易所返回委託和交易狀態到策略的原始碼分析原始碼
- 慢動作輸出 Linux 命令結果並用彩色顯示Linux
- LoadRunner測試結果分析(1)
- VNPY,從傳送交易指令到交易所的原始碼分析原始碼
- 網站漏洞滲透測試覆盤檢查結果分析網站
- 利用wps的com口用python實現excel轉pdfPythonExcel
- VNPY 自帶跨時間週期交易策略MultiTimeframeStrategy 分析
- 一文告訴你Excel融合分析如何利用Smartbi實現儀表盤效果Excel
- VNPY利用郵件引擎,把引數最佳化結果作為附件傳送給預定郵箱
- 使用IText7和miniExcel處理pdf並輸出內容Excel
- 批次檢測主機IP,並把結果生成excel檔案表格Excel
- 數字多空策略交易系統(實盤+回測+資料)
- NPOI匯出和匯入Excel,Word和PDFExcel
- 怎麼用VNPY CTP 模擬櫃檯來實現CTP 程式TICK級回測
- 分析結果,方法傳參
- Linux netstat命令結果分析Linux
- 使用cProfile針對回測進行效能分析,和結合說下提速思路
- 自動化測試工具分析和總結-實時更新
- postman的批次執行:用於多條介面測試用例批次執行,輸出介面測試測試結果Postman
- python 實現計算器功能 輸入字串,輸出相應結果Python字串
- 用Pandas讀寫Excel檔案-輸出單sheet和多sheetExcel
- C#呼叫Windows CMD命令並,返回輸出結果或錯誤資訊C#Windows
- 全鏈路效能壓測工具分析和總結-實時更新
- VNPY 基於SAR和肯特納的交易策略
- Shellshock漏洞回顧與分析測試
- Vue框架下實現匯入匯出Excel、匯出PDFVue框架Excel
- node js 批量處理pdf,提取關鍵資訊,並匯出excelJSExcel
- Jupyter Notebook實現從IB介面歷史資料獲取,寫入資料庫,策略回測和實盤交易資料庫
- vnpy,BollChannel布林線軌道策略分析
- Excel不夠用?Smartbi的Excel融合分析帶你飛Excel
- 基於web網站專案的效能測試結果分析Web網站
- HTML Table 輸出ExcelHTMLExcel