1. 程式人生 > >自己做量化交易軟體(6)通通量化歷史交易回測設計1

自己做量化交易軟體(6)通通量化歷史交易回測設計1

下面開始介紹回測功能的設計。我們前面軟體主要用的python函式設計,從現在開始使用python的類設計。 首先設計類class hpQuant(object)。初始化函式中存放一些交易變數。其中一些變數可以外部設定,例如總資金,交易手續費等等,我們按照A股交易規則,買賣有佣金,賣出需要印花稅。 所以關於交易回測的程式碼,我們存放到HP_sys.py檔案中。下面直接給出全部原始碼。讀者可複製到前面下載的通通專案目錄中。

import sys,os
import numpy as np
import pandas as pd

from HP_global import *
from HP_set import *


class hpQuant(object):
    def __init__(self):
        self.order_df=None   #下單流水
        self.trade_df=None   #交易流水
        self.security_df=None   #持倉清單
        self.money2=1000000.00  #總資金
        self.money=1000000.00  #資金
        self.priceBuy=0.00    #最後一次買入價格
        self.priceSell=999999.00  #最後一次賣出價格
        self.amount=0.00   #證券數量
        self.code=""   #證券程式碼
        self.stamp_duty=0.001   #印花稅 0.1%
        self.trading_Commission=0.0005    #交易佣金0.05%
        self.priceStopLoss=0.00   #止損價
        self.position=False   #持倉狀態
        self.stop_loss_on=True #允許止損
        self.stop_loss_num=0   #止損次數
        self.stop_loss_max=50 #止損3次,就停止交易
        self.stop_loss_range=0.05   #止損幅度
        self.trade=True   #允許交易
        self.Init()

    def Init(self):
        self.order_df = pd.DataFrame(columns = ['date', 'time','mode','code','amount','price']) 
        self.order_df =self.order_df.reset_index(level=None, drop=True ,col_level=0, col_fill='')  
        self.trade_df = pd.DataFrame(columns = ['date', 'time','mode','code','amount','price','money']) 
        self.trade_df =self.trade_df.reset_index(level=None, drop=True ,col_level=0, col_fill='')  
        self.security_df = pd.DataFrame(columns = ['code','amount','price','money']) 
        self.security_df =self.security_df.reset_index(level=None, drop=True ,col_level=0, col_fill='')  

    def PrintOrder(self):
        print(self.order_df)

    def PrintTrade(self):
        print(self.trade_df)

    def PrintSecurity(self):
        print(self.security_df)

    def Order(self,date,time,mode,code,amount,price):
        ln=len(self.order_df)
        df_new = pd.DataFrame({'date':date,'time':time,'mode':mode,'code':code,'amount':amount,'price':price},index=[ln])
        self.order_df=self.order_df.append( df_new,ignore_index=True)

        ln=len(self.trade_df)
        if mode==1:   #買入
            se=amount*price*(1+self.trading_Commission)
            self.money=self.money-se
            df_new = pd.DataFrame({'date':date,'time':time,'mode':mode,'code':code,'amount':amount,'price':price,'money':self.money},index=[ln])
            self.trade_df=self.trade_df.append( df_new,ignore_index=True)
            if len(self.security_df[self.security_df.code==code])==0 :
                df_new = pd.DataFrame({'code':code,'amount':amount,'price':se/amount,'money':se},index=[ln])
                self.security_df=self.security_df.append( df_new,ignore_index=True)
            else:
                self.security_df.index=self.security_df['code']
                self.security_df.loc[code,'amount']=self.security_df.loc[code,'amount']+amount
                self.security_df=self.security_df.reset_index(level=None, drop=True ,col_level=0, col_fill='')  
        
        ln=len(self.security_df[self.security_df.code==code])
        if mode==2 and ln>0:  #賣出
            self.security_df.index=self.security_df['code']
            am=self.security_df.loc[code,'amount']
            if am<amount :
                amount=am
               
            se=amount*price*(1-self.trading_Commission-self.stamp_duty)
            self.money=self.money+se
            df_new = pd.DataFrame({'date':date,'time':time,'mode':mode,'code':code,'amount':amount,'price':price,'money':self.money},index=[ln])
            self.trade_df=self.trade_df.append( df_new,ignore_index=True)
            am2=self.security_df.loc[code,'amount']-amount
            self.security_df.loc[code,'amount']=am2
            if am2==0:
                self.security_df=self.security_df.drop(code, axis = 0) # 在行的維度上刪除行
            self.security_df=self.security_df.reset_index(level=None, drop=True ,col_level=0, col_fill='')  


#####################回測功能#########################
    def Trade_testing(self,df,tp1,tp2,al=''):
        self.Init()
        self.trade=True   #允許交易
        myMoney=self.money2
        if (al.strip()==''):
            na='property'
        else:
            na=al 
        self.text='    ----開始回測-----\n'
        i = 0  
        ZB_l = []
        while i < len(df):  
            close=df.get_value(i, 'close')
            if (df.get_value(i, tp1) >0 and self.position==False and self.trade==True) :  #買點
                self.priceBuy=df.get_value(i, 'close')
                x=int(myMoney/(self.priceBuy*(1+self.trading_Commission))/100)
                self.amount=x*100.00
                self.Order(df.get_value(i, 'date'),'14:45:01',1,self.code,self.amount,close)
                myMoney=myMoney-self.amount*self.priceBuy*(1.00+self.trading_Commission)
                self.position=True
                self.priceStopLoss=self.priceBuy*(1-self.stop_loss_range)
                self.text=self.text+'日期:'+df.get_value(i, 'date').strftime('%Y-%m-%d')+' 買入:'+str(round(self.amount,0))+'股, 價格:'+str(round(self.priceBuy,2))+'\n'
            
            if (df.get_value(i, tp2) >0 and self.position==True and self.trade==True) : #賣點
                self.priceSell=df.get_value(i, 'close')
                myMoney=myMoney+self.amount*self.priceSell*(1.00-self.trading_Commission-self.stamp_duty)
                self.position=False
                self.Order(df.get_value(i, 'date'),'14:45:02',2,self.code,self.amount,df.get_value(i, 'close'))
                self.text=self.text+'日期:'+df.get_value(i, 'date').strftime('%Y-%m-%d')+' 賣出:'+str(round(self.amount,0))+'股, 價格:'+str(round(self.priceBuy,2))+'獲利:'+str(round((myMoney-self.money2)/self.money2*100,2))+'%\n'
                self.amount=0.00
            
            if (close<=self.priceStopLoss and self.position==True and self.trade  and self.stop_loss_on):  #止損
                self.priceSell=self.priceStopLoss-0.01
                myMoney=myMoney+self.amount*self.priceSell*(1.00-self.trading_Commission-self.stamp_duty)
                self.position=False
                self.stop_loss_num=self.stop_loss_num+1
                self.Order(df.get_value(i, 'date'),'14:45:02',2,self.code,self.amount,df.get_value(i, 'close'))
                self.text=self.text+'日期:'+df.get_value(i, 'date').strftime('%Y-%m-%d')+' 止損:'+str(round(self.amount,0))+'股, 價格:'+str(round(self.priceBuy,2))+'獲利:'+str(round((myMoney-self.money2)/self.money2*100,2))+'%\n'
                self.amount=0.00
                if (self.stop_loss_num>=self.stop_loss_max):
                    self.trade=False
                

            y= (myMoney+self.amount*close-self.money2)/self.money2 *100 
            ZB_l.append(y)  
            i = i + 1          
            
        ZB_s = pd.Series(ZB_l)  
        ZB = pd.Series(ZB_s, name = na)  
        df = df.join(ZB)  
        y= (myMoney+self.amount*close-self.money2)/self.money2  *100
        self.text=self.text+'總投入:1000000.00,最終獲利幅度'+str(round(y,0))+'%\n'
            
        return df

使用方法:

import HP_lib as mylib
from HP_sys import *

##回測
tt=hpQuant()   ##初始化類

#下面是使用者可設定資訊。
#        self.money2=1000000.00  #總資金
#        self.code=""   #證券程式碼
#        self.stamp_duty=0.001   #印花稅 0.1%
#        self.trading_Commission=0.0005    #交易佣金0.05%
#        self.stop_loss_on=True #允許止損
#        self.stop_loss_max=50 #止損3次,就停止交易
#        self.stop_loss_range=0.05   #止損幅度

tt.code=code   #證券程式碼,必須輸入
tt.stop_loss_on=False    #關閉自動止損
df3=tt.Trade_testing(df2,'B1','S1','HL')   #開始回測
print('\n列印交易過程')
tt.PrintTrade()    #列印交易過程
print('\n列印持倉資訊')
tt.PrintSecurity()   #列印持倉資訊
print('\n 列印內部交易記錄資訊')
print(tt.text)     #列印交易資訊

具體使用,我在下一篇介紹一個簡單的回測例子。