In [19]:
#!/Tsan/bin/python
# -*- coding: utf-8 -*-

In [20]:
#"""此note book为股票回测框架的示例"""

In [21]:
# Libraries to use
from __future__ import division 
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime

In [22]:
# Import My own library for factor testing
from SingleFactorTest import factorFilterFunctions as ff
from BackTestingEngine import backTestingEngine as bte
#from config import *

In [23]:
path = ff.data_path

In [24]:
startTime =  datetime.strptime('20160504', '%Y%m%d')
endTime = datetime.strptime('20170228', '%Y%m%d')
initstartTime =  datetime.strptime('20160304', '%Y%m%d')
initendTime = datetime.strptime('20170328', '%Y%m%d')

In [25]:
filenameAdjOpen = 'OwnfactorAdjustedOpen.h5'
filenameAdjClose = 'OwnfactorAdjustedClose.h5'
filenameVolume = 'LZ_CN_STKA_QUOTE_TVOLUME.h5'

In [26]:
# 初始化
test = bte.StkBacktesting(path)

In [27]:
test.setInitCap(50000000)
test.availableCashNow


Out[27]:
50000000

In [28]:
# 添加数据
test.addData('adjOpen',filenameAdjOpen)
test.addData('adjClose',filenameAdjClose)
test.addData('volume',filenameVolume)

In [29]:
# 截取回测区间和初始化区间
test.setBackTestingPeriod(startTime,endTime)
test.setInitialPeriod(initstartTime,initendTime)

In [30]:
# 双均线筛选买卖股
ma5 = test.dataDict['adjClose'].rolling(window=5, min_periods=5).mean()
ma20 = test.dataDict['adjClose'].rolling(window=20, min_periods=20).mean()
buyStk = ((ma5 > ma20) & ((ma5 < ma20).shift(1) )).shift(1).loc[test.backTestingDateList.tolist()]
sellStk = ((ma5 < ma20) & ((ma5 > ma20).shift(1) )).shift(1).loc[test.backTestingDateList]

In [31]:
test.getAllPosition()


Out[31]:
{}

In [32]:
# 按天循环
for date in  test.backTestingDateList:
    #todayindex = test.backTestingDateList.tolist().index(date)
    #yesterday = test.backTestingDateList[todayindex -1]
    #print yesterday

    # 切片确定当天的买卖股票
    sellslice = sellStk.loc[date]
    sellList = sellslice.loc[sellslice==True].index.tolist()
    #print 'before',len(sellList)
    buyslice = buyStk.loc[date]
    buyList = buyslice.loc[buyslice==True].index.tolist()
    # 买卖单
    buyOrders = [test.makeOrder(date,stkID,100,20,1) for stkID in buyList]
    
    # 区分有无持仓时,只有有持仓时才可以卖,并且顺序永远是先卖后买   
    if test.getCurrentPosition():
        
        print date, 'Current position Num',len(test.getCurrentPosition())
        
        sellList = list(set(sellList) & set(test.getCurrentPosition().keys()))
        sellOrders = [test.makeOrder(date,stkID,test.getCurrentPosition()[stkID].volume,20,-1) for stkID in sellList]
        totalOrders = sellOrders + buyOrders
        #print 'buyNumber',len(buyOrders)
        #print 'sellNumber', len(sellList)
    else:
        #print 'Current position is 0'
        totalOrders = buyOrders
    #print len(totalOrders)
    test.allOrdersDict[date] = totalOrders  # 保存order到字典里
    test.crossOrder(date)     #  撮合
    #test.updateHoldingPnl(date)
    #print date,'Wrong one', test.getAllPosition()[date].__len__()
    #print date,'compare',len(test.getCurrentPosition())
    #try:
    #    print yesterday,'yester',test.getAllPosition()[yesterday].__len__()
    #except:
     #   pass


2016-05-05 00:00:00 Current position Num 110
2016-05-06 00:00:00 Current position Num 238
2016-05-09 00:00:00 Current position Num 420
2016-05-10 00:00:00 Current position Num 510
2016-05-11 00:00:00 Current position Num 424
2016-05-12 00:00:00 Current position Num 304
2016-05-13 00:00:00 Current position Num 227
2016-05-16 00:00:00 Current position Num 168
2016-05-17 00:00:00 Current position Num 164
2016-05-18 00:00:00 Current position Num 204
2016-05-19 00:00:00 Current position Num 254
2016-05-20 00:00:00 Current position Num 274
2016-05-23 00:00:00 Current position Num 277
2016-05-24 00:00:00 Current position Num 306
2016-05-25 00:00:00 Current position Num 317
2016-05-26 00:00:00 Current position Num 329
2016-05-27 00:00:00 Current position Num 387
2016-05-30 00:00:00 Current position Num 490
2016-05-31 00:00:00 Current position Num 574
2016-06-01 00:00:00 Current position Num 589
2016-06-02 00:00:00 Current position Num 879
2016-06-03 00:00:00 Current position Num 1331
2016-06-06 00:00:00 Current position Num 1909
2016-06-07 00:00:00 Current position Num 2208
2016-06-08 00:00:00 Current position Num 2381
2016-06-13 00:00:00 Current position Num 2400
2016-06-14 00:00:00 Current position Num 2403
2016-06-15 00:00:00 Current position Num 2314
2016-06-16 00:00:00 Current position Num 2051
2016-06-17 00:00:00 Current position Num 1757
2016-06-20 00:00:00 Current position Num 1397
2016-06-21 00:00:00 Current position Num 1176
2016-06-22 00:00:00 Current position Num 1369
2016-06-23 00:00:00 Current position Num 1498
2016-06-24 00:00:00 Current position Num 1541
2016-06-27 00:00:00 Current position Num 1595
2016-06-28 00:00:00 Current position Num 1501
2016-06-29 00:00:00 Current position Num 1516
2016-06-30 00:00:00 Current position Num 1636
2016-07-01 00:00:00 Current position Num 1667
2016-07-04 00:00:00 Current position Num 1799
2016-07-05 00:00:00 Current position Num 2043
2016-07-06 00:00:00 Current position Num 2209
2016-07-07 00:00:00 Current position Num 2293
2016-07-08 00:00:00 Current position Num 2331
2016-07-11 00:00:00 Current position Num 2385
2016-07-12 00:00:00 Current position Num 2425
2016-07-13 00:00:00 Current position Num 2381
2016-07-14 00:00:00 Current position Num 2306
2016-07-15 00:00:00 Current position Num 2269
2016-07-18 00:00:00 Current position Num 2218
2016-07-19 00:00:00 Current position Num 2192
2016-07-20 00:00:00 Current position Num 2161
2016-07-21 00:00:00 Current position Num 2134
2016-07-22 00:00:00 Current position Num 2066
2016-07-25 00:00:00 Current position Num 1979
2016-07-26 00:00:00 Current position Num 1854
2016-07-27 00:00:00 Current position Num 1753
2016-07-28 00:00:00 Current position Num 1696
2016-07-29 00:00:00 Current position Num 1337
2016-08-01 00:00:00 Current position Num 1029
2016-08-02 00:00:00 Current position Num 824
2016-08-03 00:00:00 Current position Num 640
2016-08-04 00:00:00 Current position Num 533
2016-08-05 00:00:00 Current position Num 528
2016-08-08 00:00:00 Current position Num 522
2016-08-09 00:00:00 Current position Num 528
2016-08-10 00:00:00 Current position Num 589
2016-08-11 00:00:00 Current position Num 693
2016-08-12 00:00:00 Current position Num 797
2016-08-15 00:00:00 Current position Num 864
2016-08-16 00:00:00 Current position Num 986
2016-08-17 00:00:00 Current position Num 1180
2016-08-18 00:00:00 Current position Num 1374
2016-08-19 00:00:00 Current position Num 1664
2016-08-22 00:00:00 Current position Num 2110
2016-08-23 00:00:00 Current position Num 2408
2016-08-24 00:00:00 Current position Num 2433
2016-08-25 00:00:00 Current position Num 2417
2016-08-26 00:00:00 Current position Num 2322
2016-08-29 00:00:00 Current position Num 2137
2016-08-30 00:00:00 Current position Num 1946
2016-08-31 00:00:00 Current position Num 1859
2016-09-01 00:00:00 Current position Num 1740
2016-09-02 00:00:00 Current position Num 1640
2016-09-05 00:00:00 Current position Num 1577
2016-09-06 00:00:00 Current position Num 1461
2016-09-07 00:00:00 Current position Num 1312
2016-09-08 00:00:00 Current position Num 1315
2016-09-09 00:00:00 Current position Num 1310
2016-09-12 00:00:00 Current position Num 1393
2016-09-13 00:00:00 Current position Num 1469
2016-09-14 00:00:00 Current position Num 1334
2016-09-19 00:00:00 Current position Num 1166
2016-09-20 00:00:00 Current position Num 1009
2016-09-21 00:00:00 Current position Num 907
2016-09-22 00:00:00 Current position Num 854
2016-09-23 00:00:00 Current position Num 922
2016-09-26 00:00:00 Current position Num 993
2016-09-27 00:00:00 Current position Num 1109
2016-09-28 00:00:00 Current position Num 1051
2016-09-29 00:00:00 Current position Num 1013
2016-09-30 00:00:00 Current position Num 964
2016-10-10 00:00:00 Current position Num 928
2016-10-11 00:00:00 Current position Num 924
2016-10-12 00:00:00 Current position Num 1107
2016-10-13 00:00:00 Current position Num 1290
2016-10-14 00:00:00 Current position Num 1571
2016-10-17 00:00:00 Current position Num 1913
2016-10-18 00:00:00 Current position Num 2172
2016-10-19 00:00:00 Current position Num 2193
2016-10-20 00:00:00 Current position Num 2240
2016-10-21 00:00:00 Current position Num 2227
2016-10-24 00:00:00 Current position Num 2211
2016-10-25 00:00:00 Current position Num 2184
2016-10-26 00:00:00 Current position Num 2278
2016-10-27 00:00:00 Current position Num 2265
2016-10-28 00:00:00 Current position Num 2276
2016-10-31 00:00:00 Current position Num 2259
2016-11-01 00:00:00 Current position Num 2222
2016-11-02 00:00:00 Current position Num 2017
2016-11-03 00:00:00 Current position Num 1829
2016-11-04 00:00:00 Current position Num 1620
2016-11-07 00:00:00 Current position Num 1507
2016-11-08 00:00:00 Current position Num 1485
2016-11-09 00:00:00 Current position Num 1529
2016-11-10 00:00:00 Current position Num 1530
2016-11-11 00:00:00 Current position Num 1539
2016-11-14 00:00:00 Current position Num 1597
2016-11-15 00:00:00 Current position Num 1702
2016-11-16 00:00:00 Current position Num 1807
2016-11-17 00:00:00 Current position Num 1932
2016-11-18 00:00:00 Current position Num 2132
2016-11-21 00:00:00 Current position Num 2194
2016-11-22 00:00:00 Current position Num 2184
2016-11-23 00:00:00 Current position Num 2171
2016-11-24 00:00:00 Current position Num 2170
2016-11-25 00:00:00 Current position Num 2114
2016-11-28 00:00:00 Current position Num 2044
2016-11-29 00:00:00 Current position Num 1987
2016-11-30 00:00:00 Current position Num 1883
2016-12-01 00:00:00 Current position Num 1629
2016-12-02 00:00:00 Current position Num 1407
2016-12-05 00:00:00 Current position Num 1281
2016-12-06 00:00:00 Current position Num 1081
2016-12-07 00:00:00 Current position Num 876
2016-12-08 00:00:00 Current position Num 771
2016-12-09 00:00:00 Current position Num 714
2016-12-12 00:00:00 Current position Num 679
2016-12-13 00:00:00 Current position Num 670
2016-12-14 00:00:00 Current position Num 588
2016-12-15 00:00:00 Current position Num 537
2016-12-16 00:00:00 Current position Num 470
2016-12-19 00:00:00 Current position Num 445
2016-12-20 00:00:00 Current position Num 427
2016-12-21 00:00:00 Current position Num 482
2016-12-22 00:00:00 Current position Num 547
2016-12-23 00:00:00 Current position Num 644
2016-12-26 00:00:00 Current position Num 733
2016-12-27 00:00:00 Current position Num 768
2016-12-28 00:00:00 Current position Num 811
2016-12-29 00:00:00 Current position Num 874
2016-12-30 00:00:00 Current position Num 870
2017-01-03 00:00:00 Current position Num 884
2017-01-04 00:00:00 Current position Num 972
2017-01-05 00:00:00 Current position Num 1076
2017-01-06 00:00:00 Current position Num 1264
2017-01-09 00:00:00 Current position Num 1553
2017-01-10 00:00:00 Current position Num 1804
2017-01-11 00:00:00 Current position Num 2039
2017-01-12 00:00:00 Current position Num 2030
2017-01-13 00:00:00 Current position Num 1857
2017-01-16 00:00:00 Current position Num 1622
2017-01-17 00:00:00 Current position Num 1335
2017-01-18 00:00:00 Current position Num 867
2017-01-19 00:00:00 Current position Num 635
2017-01-20 00:00:00 Current position Num 515
2017-01-23 00:00:00 Current position Num 480
2017-01-24 00:00:00 Current position Num 493
2017-01-25 00:00:00 Current position Num 557
2017-01-26 00:00:00 Current position Num 591
2017-02-03 00:00:00 Current position Num 668
2017-02-06 00:00:00 Current position Num 779
2017-02-07 00:00:00 Current position Num 849
2017-02-08 00:00:00 Current position Num 935
2017-02-09 00:00:00 Current position Num 1085
2017-02-10 00:00:00 Current position Num 1318
2017-02-13 00:00:00 Current position Num 1651
2017-02-14 00:00:00 Current position Num 2052
2017-02-15 00:00:00 Current position Num 2396
2017-02-16 00:00:00 Current position Num 2582
2017-02-17 00:00:00 Current position Num 2601
2017-02-20 00:00:00 Current position Num 2584
2017-02-21 00:00:00 Current position Num 2497
2017-02-22 00:00:00 Current position Num 2321
2017-02-23 00:00:00 Current position Num 2240
2017-02-24 00:00:00 Current position Num 2239
2017-02-27 00:00:00 Current position Num 2217
2017-02-28 00:00:00 Current position Num 2313

In [33]:
#for i,j in test._allCurrentPositionDict.iteritems():
#    print i,j.values

In [34]:
positiondf = pd.DataFrame.from_dict(test.getAllPosition(), orient='index')

In [35]:
def converToVolume(holdingclass):
    try:
        volume = holdingclass.volume
    except:
        volume = np.NaN
    return volume

In [37]:
positiondf.applymap(converToVolume).fillna(0).tail(10)


Out[37]:
000916.SZ 300081.SZ 600190.SH 000713.SZ 300192.SZ 603123.SH 300034.SZ 000528.SZ 002665.SZ 000685.SZ ... 603838.SH 002608.SZ 002280.SZ 300573.SZ 600675.SH 603058.SH 300581.SZ 300585.SZ 300587.SZ 603416.SH
2017-02-15 100.0 100.0 100.0 0.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-16 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-17 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-20 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-21 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-22 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-23 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-24 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-27 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 100.0 100.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0
2017-02-28 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ... 100.0 100.0 100.0 100.0 0.0 100.0 100.0 100.0 100.0 100.0

10 rows × 3003 columns


In [38]:
test.showBackTestingResult()


2017-11-10 18:28:19.703000	期末净值:	0.9969
2017-11-10 18:28:19.704000	总盈亏:	-154,657.0826
2017-11-10 18:28:19.704000	年化收益率:	-0.0002
2017-11-10 18:28:19.704000	年化波动率:	0.0021
2017-11-10 18:28:19.704000	夏普比率:	-0.089
2017-11-10 18:28:19.704000	最大回撤: 	0.0091
2017-11-10 18:28:19.704000	胜率: 	0.2935
2017-11-10 18:28:19.704000	换手率: 	0.1476
2017-11-10 18:28:19.704000	总手续费: 	195,720.8826