哈尔兹法则策略量化四(继续优化买点,加入均线系统以及大盘指数)

哈尔兹法则策略量化三中,我们对哈尔兹法则的买入条件继续进行了优化,在原来股从低价上涨10%的基础上加入5日均线>10均线>20日均线,近三年收益如下图所示:


我们看到在策略三中,收益及收益率对比策略一,策略二都有改善,尤其是2019年收益达到了29.65,但是正收益率最高只有0.5。

我们今天继续对买点进行优化,即将我们的量化交易策略改为:

在原来股价从低价上涨10%的基础上加入5日均线>10均线>20日均线,以及大盘走势判断,具体就是在量化交易策略三的基础上创业板指数和深圳指数不是处于5日均线<10日均线<20日均线的下跌情况,python代码买点如下:

(df_temp.close[j]-close_min_new)/close_min_new >0.1 and ma5_temp[j] > ma10_temp[j] > ma20_temp[j]and (not ma5_chuangzhi[j-1] < ma10_chuangzhi[j-1] < ma20_chuangzhi[j-1])and (not ma5_shenzhen[j-1] < ma10_shenzhen[j-1] < ma20_shenzhen[j-1])

代码稍做解释:

(df_temp.close[j]-close_min_new)/close_min_new >0.1

close_min_new,60天内最低价

(df_temp.close[j]-close_min_new)/close_min_new > 0.1,表示

股价从低价上涨10%

ma5_temp[j] > ma10_temp[j] > ma20_temp[j]

表示5日均线>10均线>20日均线

not ma5_chuangzhi[j-1] < ma10_chuangzhi[j-1] < ma20_chuangzhi[j-1])and (not ma5_shenzhen[j-1] < ma10_shenzhen[j-1] < ma20_shenzhen[j-1]

表示创业板指数和深圳指数不是处于5日均线<10日均线<20日均线的下跌

近三年收益如下:


我们看到收益以及正收益率比起哈尔兹法则策略量化三都是明显要差一些,所以在某些策略,过于强调大盘其实不对的,这个也就是经常说的重个股轻大盘。

Python代码部分如下:

# -*- coding: utf-8 -*-

import numpyas np

import pandasas pd

import matplotlib.pyplotas plt

import os

import shutil

import time

import matplotlib

def Haerzi(start,end):

mairuhou_mark =0

    zhengshouyi_num =0

    fushouyi_num =0

    cur_dir = os.getcwd()# get current path

    folder_name ='result'

    dir_new = os.path.join(cur_dir, folder_name)

end_date = ['2019/12/31','2019/12/30','2019/12/29','2019/12/28']

#删掉结果

    if os.path.exists(dir_new +"\\" + start.replace("/","_") +"__" + end.replace("/","_") +"celie_xiangxi" +'.txt'):

os.remove(dir_new +"\\" + start.replace("/","_") +"__" + end.replace("/","_") +"celie_xiangxi" +'.txt')

if os.path.exists(dir_new +"\\" + start.replace("/","_") +"__" + end.replace("/","_") +"dangtian_buy" +'.txt'):

os.remove(dir_new +"\\" + start.replace("/","_") +"__" + end.replace("/","_") +"dangtian_buy" +'.txt')

if os.path.exists(dir_new +"\\" + start.replace("/","_") +"__" + end.replace("/","_") +'"dangtian_sell"' +'.txt'):

os.remove(dir_new +"\\" + start.replace("/","_") +"__" + end.replace("/","_") +'"dangtian_sell"' +'.txt')

#设置路径

    dir_list = []

lujing =r'C:\gupiao\gupiaoci'

    for iin os.listdir(r'C:\gupiao\gupiaoci'):

a = i.split('.')[0]

if a[0] !='3':

dir_list.append(lujing+'\\'+i)

#创业板指数

    df = pd.read_table(r'C:\gupiao\gupiaoci' +"\\399006.txt",header=1,usecols=range(6), parse_dates=[0], index_col=0,encoding='gb2312')

df.index.rename('date', inplace=True)

df.rename(columns={'    开盘':'open', '    最高':'high', '    最低':'low', '    收盘':'close','    成交量':'vol'}, inplace=True)

df = df.drop('数据来源:通达信')

df.close = df.close.astype(np.float32)#设置为32位,4字节,默认64位,8字节,append到list之后就会多小数位

    df.low = df.low.astype(np.float32)#设置为32位,4字节,默认64位,8字节,append到list之后就会多小数位

    df.vol = df.vol.astype(np.int64)

df2 = df[start:end][:len(df.vol)-1]

#均线

    ma5_chuangzhi = df2.close.rolling(window=5,center=False).mean()

ma5_chuangzhi = ma5_chuangzhi [start:end]

ma10_chuangzhi = df2.close.rolling(window=10,center=False).mean()

ma10_chuangzhi = ma10_chuangzhi [start:end]

ma20_chuangzhi = df2.close.rolling(window=20,center=False).mean()

ma20_chuangzhi = ma20_chuangzhi [start:end]

#深圳指数

    df = pd.read_table(r'C:\gupiao\gupiaoci' +"\\399106.txt",header=1,usecols=range(6), parse_dates=[0], index_col=0,encoding='gb2312')

df.index.rename('date', inplace=True)

df.rename(columns={'    开盘':'open', '    最高':'high', '    最低':'low', '    收盘':'close','    成交量':'vol'}, inplace=True)

df = df.drop('数据来源:通达信')

df.close = df.close.astype(np.float32)#设置为32位,4字节,默认64位,8字节,append到list之后就会多小数位

    df.low = df.low.astype(np.float32)#设置为32位,4字节,默认64位,8字节,append到list之后就会多小数位

    df.vol = df.vol.astype(np.int64)

df2 = df[start:end][:len(df.vol)-1]

#均线

    ma5_shenzhen = df2.close.rolling(window=5,center=False).mean()

ma5_shenzhen = ma5_shenzhen[start:end]

ma10_shenzhen = df2.close.rolling(window=10,center=False).mean()

ma10_shenzhen = ma10_shenzhen[start:end]

ma20_shenzhen = df2.close.rolling(window=20,center=False).mean()

ma20_shenzhen = ma20_shenzhen[start:end]

#个股

    total_shouyi=1

    total_date_buy = []

total_date_sell = []

buy_date_zhengshouyi = []

buy_date_fushouyi = []

for jin dir_list:

#获取数据

        name = (j.split('\\')[-1]).split('.')[0]

df = pd.read_table(j,header=1,usecols=range(6), parse_dates=[0], index_col=0,encoding='gb2312')

df.index.rename('date', inplace=True)

df.rename(columns={'    开盘':'open', '    最高':'high', '    最低':'low', '    收盘':'close','    成交量':'vol'}, inplace=True)

df = df.drop('数据来源:通达信')

df.close = df.close.astype(np.float32)#设置为32位,4字节,默认64位,8字节,append到list之后就会多小数位

        df.low = df.low.astype(np.float32)#设置为32位,4字节,默认64位,8字节,append到list之后就会多小数位

        df.vol = df.vol.astype(np.int64)

df2 = df[start:end][:len(df.vol)-1]

df = df[start:end]

#均线

        ma5 = df2.close.rolling(window=5,center=False).mean()

ma5= ma5[start:end]

ma3 = df2.close.rolling(window=3,center=False).mean()

ma3= ma3[start:end]

ma8 = df2.close.rolling(window=8, center=False).mean()

ma8 = ma8[start:end]

ma15 = df2.close.rolling(window=15, center=False).mean()

ma15 = ma15[start:end]

ma10 = df2.close.rolling(window=10,center=False).mean()

ma10= ma10[start:end]

ma12 = df2.close.rolling(window=12, center=False).mean()

ma12 = ma12[start:end]

ma20 = df2.close.rolling(window=20,center=False).mean()

ma20= ma20[start:end]

ma30 = df2.close.rolling(window=30,center=False).mean()

ma30 = ma30[start:end]

ma60 = df2.close.rolling(window=60,center=False).mean()

ma60 = ma60[start:end]

ma120 = df2.close.rolling(window=120,center=False).mean()

ma120 = ma120[start:end]

ma200 = df2.close.rolling(window=200, center=False).mean()

ma200 = ma200[start:end]

ma250 = df2.close.rolling(window=250,center=False).mean()

ma250 = ma250[start:end]

#均量线

        vol5 = df2.vol.rolling(window=5,center=False).mean()

vol5 = vol5[start:end]

vol3 = df2.vol.rolling(window=3,center=False).mean()

vol3 = vol3[start:end]

vol8 = df2.vol.rolling(window=8,center=False).mean()

vol8 = vol8[start:end]

vol10 = df2.vol.rolling(window=10,center=False).mean()

vol10 = vol10[start:end]

vol20 = df2.vol.rolling(window=20,center=False).mean()

vol20 = vol20[start:end]

vol15 = df2.vol.rolling(window=15,center=False).mean()

vol15 = vol15[start:end]

vol30 = df2.vol.rolling(window=30,center=False).mean()

vol30 = vol30[start:end]

vol60 = df2.vol.rolling(window=60, center=False).mean()

vol60 = vol60[start:end]

#设置初始化数据

#买入条件,buy_status = True,其次是chicang_status = False

        chicang_status =False#chicang_status==False的时候表示空仓状态,可以买入,买入之后需要将其设置为True,表示股票为持有状态

        buy_status =False#初始化buy的状态为False,当遇到买点出现时,设置状态为True,表示之后可以买入

        buy_price = []

buy_date = []

sell_price = []

sell_date = []

low_vol = []

low_vol_index = []

fengexian_mark =0

        #low_vol

        df_temp = df

temp_vol = df.vol

temp_index = df.index

ma3_temp = ma3

ma5_temp = ma5

ma8_temp = ma8

ma15_temp = ma15

ma10_temp = ma10

ma12_temp = ma12

ma20_temp = ma20

ma30_temp = ma30

ma60_temp = ma60

ma120_temp = ma120

ma200_temp = ma200

ma250_temp = ma250

vol5_temp = vol5

vol3_temp = vol3

vol8_temp = vol8

vol15_temp = vol15

vol10_temp = vol10

vol20_temp = vol20

vol30_temp = vol30

vol60_temp = vol60

temp_vol_max =0

        for jin range(60,len(temp_vol)):

close_min = df_temp.close[j-60:j-1].min()#60天内最低价

            if buy_status ==False and  chicang_status ==False and df_temp.close[j] < close_min:

buy_status =True#买点出现时,设置状态为True,表示之后可以买入

                vol_max_dangtian_index = temp_index[j]

close_min_new = df_temp.close[j]

elif buy_status ==True and chicang_status ==False:

if df_temp.at[temp_index[j-1],'close'] >=300 or (df_temp.high[j]-df_temp.close[j-1])/df_temp.close[j-1] < -0.09:

chicang_status =False

                    buy_status =False

break

                elif (df_temp.close[j]-close_min_new)/close_min_new >0.1 and ma5_temp[j] > ma10_temp[j] > ma20_temp[j]and (not ma5_chuangzhi[j-1] < ma10_chuangzhi[j-1] < ma20_chuangzhi[j-1])and (not ma5_shenzhen[j-1] < ma10_shenzhen[j-1] < ma20_shenzhen[j-1]):#买点优化,即在哈尔兹法则的买入条件,股从低价上涨10%的基础上加入5日均线大于10均线​

                    if len(gupiaochichang) >=1:

for gupiaochichang_itemin gupiaochichang:

if gupiaochichang_item[0] == temp_index[j]and gupiaochichang_item[1] >=1:

#print(gupiaochichang_item)

                                chicang_status =False

                                buy_status =False

                        if chicang_status ==False and buy_status ==False:

continue

                    chicang_status =True

                    buy_status =False#买入之后设置状态为False

                    buy_price_m = df_temp.at[temp_index[j],'close']

buy_date_temp = temp_index[j]

buy_price.append(df_temp.at[temp_index[j],'close'])

buy_date.append(temp_index[j])

total_date_buy.append([name,temp_index[j]])

fengexian_mark =1

                    close_max = df_temp.close[j]#加入买入当天就是当前最高价

#股票持仓,买日期加1,买日期不在list,则加入

                    for gupiaochichuang_itemin gupiaochichang:

if gupiaochichuang_item[0] == temp_index[j]:

gupiaochichuang_item[1] +=1

                    if len(gupiaochichang) ==0:

gupiaochichang.append([temp_index[j],1])

else:

for i22in range(len(gupiaochichang)):

if len(gupiaochichang) !=0 and i22 ==len(gupiaochichang) -1 and gupiaochichang[i22][0] != temp_index[j]:#找到最后一个还没有找到买日期,加将买日期加入

                                gupiaochichang.append([temp_index[j],1])

#存结果

                    with open(dir_new +"\\" + start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write("股票名称--" + name +'\n' +"开始日期--" + start +'\n' +"结束日期--" + end +'\n' )

f.write("最大vol/当天vol 大于20当天日期----->" +str(vol_max_dangtian_index) +'\n')

f.write('\n' +"股票名称--" + name +"--买入价格--" +"--步长--"  +"--" +"--j--" +str(j) +"--" +str(df_temp.at[temp_index[j],'close']) +"--买入日期--" +str(temp_index[j]))

elif chicang_status ==True:

if close_max < df_temp.close[j]:

close_max = df_temp.close[j]#动态计算最高点价格

                if (close_max -  df_temp.close[j])/ df_temp.close[j] >=0.1:#最高点下跌10%,卖出

                    chicang_status =False

                    sell_price.append(df_temp.close[j])

sell_date.append(temp_index[j])

total_date_sell.append([name,temp_index[j]])

if (df_temp.close[j]-buy_price_m)/buy_price_m >0:

zhengshouyi_num +=1#正收益次数加1

                        buy_date_zhengshouyi.append(buy_date_temp)

else:

fushouyi_num +=1#负收益次数加1

                        buy_date_fushouyi.append(buy_date_temp)

total_shouyi *= (1 + (df_temp.close[j]-buy_price_m)/buy_price_m)

mairuhou_mark =0

                    #存结果

                    with open(dir_new +"\\" + start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' +"股票名称--" + name +"--最高点下跌10%,卖出价格--" +"--步长--" +"--" +"--j--" +str(j) +"--" +str(df_temp.close[j]) +"--卖出日期--" +str(temp_index[j]))

elif (df_temp.close[j] - buy_price_m)/buy_price_m < -0.05:

chicang_status =False

                    sell_price.append(df_temp.close[j])

sell_date.append(temp_index[j])

total_date_sell.append([name,temp_index[j]])

fushouyi_num +=1#负收益次数加1

                    total_shouyi *= (1 -0.05)

mairuhou_mark =0

                    # buy_date_fushouyi.append([name,buy_date_temp])

                    buy_date_fushouyi.append(buy_date_temp)

#存结果

                    with open(dir_new +"\\" + start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' +"股票名称--" + name +"--止损-0.05,卖出价格--" +"--步长--" +"--" +"--j--" +str(j) +"--" +str(df_temp.close[j]) +"--卖出日期--" +str(temp_index[j]))

elif mairuhou_mark >=10:

total_shouyi *= (1 + (df_temp.close[j] - buy_price_m)/buy_price_m)

chicang_status =False

                    sell_price.append(df_temp.close[j])

sell_date.append(temp_index[j])

total_date_sell.append([name,temp_index[j]])

mairuhou_mark =0

                    if (df_temp.close[j] - buy_price_m)/(buy_price_m) >0:

zhengshouyi_num +=1

                        buy_date_zhengshouyi.append(buy_date_temp)

#print("持有超过10天卖出:",(df_temp.close[j] - buy_price_m)/(buy_price_m))

#存结果

                        with open(dir_new +"\\" + start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' +"股票名称--" + name +"--持有超过5天卖出,大于0.01,卖出价格--" +"--" +"--j--" +str(j) +"--" +str(df_temp.close[j]) +"--卖出日期--" +str(temp_index[j]))

else:

fushouyi_num +=1

                        buy_date_fushouyi.append(buy_date_temp)

#print("持有超过10天卖出:",(df_temp.close[j] - buy_price_m) / (buy_price_m ))

#存结果

                        with open(dir_new +"\\" +  start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' +"股票名称--" + name +"--持有超过15天卖出,小于0.01,大于0,卖出价格--"  +"--j--" +str(j) +"--" +str(df_temp.close[j]) +"--卖出日期--" +str(temp_index[j]))

else:

mairuhou_mark +=1

        gupiaochichang.sort(key=lambda x:x[0])

#if zhengshouyi_num+fushouyi_num != 0:

#print(start,"----",end,"total_shouyi=",'%.2f'%(total_shouyi),"概率",'%.2f'%(zhengshouyi_num/(zhengshouyi_num+fushouyi_num)),"正收益次数->",zhengshouyi_num,"负收益次数->",fushouyi_num)

#存结果

        cur_dir = os.getcwd()# get current path

        folder_name ='result'

        dir_new = os.path.join(cur_dir, folder_name)

#存买入,卖出价格,日期

        if len(buy_price) >len(sell_price):

if buy_date[-1]in end_date:

with open(dir_new +"\\" +  start.replace("/","_") +"__" +end.replace("/","_") +"dangtian_buy" +'.txt','a')as f:

f.writelines('\n' + name +"--" +str(buy_date[-1]) +'\n' +'buy: ' +str(buy_price[-1])  +'\n')

if len(sell_price) !=0:

if sell_date[-1]in end_date:

with open(dir_new +"\\" +  start.replace("/","_") +"__" +end.replace("/","_") +"dangtian_sell" +'.txt','a')as f:

for rrin range(len(sell_price)):

if rr ==0:

f.writelines('\n' + name +'\n' +'buy: ' +str(buy_price[rr]) +str(buy_date[rr]) +'\n' +'sell: ' +str(sell_price[rr]) +str(sell_date[rr]) +'\n')

else:

f.writelines('buy: ' +str(buy_price[rr]) +str(buy_date[rr]) +'\n' +'sell: ' +str(sell_price[rr]) +str(sell_date[rr]) +'\n')

if zhengshouyi_num+fushouyi_num !=0:

zshouyi =float(zhengshouyi_num/(zhengshouyi_num+fushouyi_num))

fshouyi =float(fushouyi_num/(zhengshouyi_num+fushouyi_num))

total_num = zhengshouyi_num+fushouyi_num

total_date_buy.sort(key=lambda x:x[1])

total_date_sell.sort(key=lambda x:x[1])

x = []

y = []

for iin buy_date_zhengshouyi:

if inot in x:

x.append(i)

for iin buy_date_fushouyi:

if inot in y:

y.append(i)

if fengexian_mark ==1:

with open(dir_new +"\\" +  start.replace("/","_") +"__" + end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' +'\n' +"--------------------分割线----------------------" +'\n' +'\n')

buy_date_zhengshouyi_count = []

buy_date_fushouyi_count = []

i =0

    x.sort()

y.sort()

for iin x:

if buy_date_zhengshouyi.count(i) >=0:

with open(dir_new +"\\" +  start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' +"正收益买日期--" +str(buy_date_zhengshouyi.count(i)) +"--" +str(i))

buy_date_zhengshouyi_count.append(buy_date_zhengshouyi.count(i))

with open(dir_new +"\\" + start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' )

for iin y:

if buy_date_fushouyi.count(i) >=0:

with open(dir_new +"\\" + start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' +"负收益买日期--" +str(buy_date_fushouyi.count(i)) +"--" +str(i))

buy_date_fushouyi_count.append(buy_date_fushouyi.count(i))

if zhengshouyi_num+fushouyi_num !=0:

print(start,"----",end,"total_shouyi=",'%.2f'%(total_shouyi),"概率",'%.2f'%(zhengshouyi_num/(zhengshouyi_num+fushouyi_num)),"正收益次数->",zhengshouyi_num,"负收益次数->",fushouyi_num)

with open(dir_new +"\\" +  start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt','a')as f:

f.write('\n' +'\n' +"正收益买日期count--" +str(len(buy_date_zhengshouyi_count)) +"--" +str(buy_date_zhengshouyi_count))

f.write('\n' +"负收益买日期count--" +str(len(buy_date_fushouyi_count)) +"--" +str(buy_date_fushouyi_count))

f.write('\n' +"买卖总次数" +str(zhengshouyi_num+fushouyi_num) +"--正收益买概率--" +str('%.2f'%(zhengshouyi_num/(zhengshouyi_num + fushouyi_num))) +"--正收益次数--" +str(zhengshouyi_num))

for iin range(len(gupiaochichang)):

if i ==0:

f.write('\n' +"买日期count:" +'\n' +str(gupiaochichang[i]))

else:

f.write('\n' +str(gupiaochichang[i]))

shutil.copy(dir_new +"\\" +  start.replace("/","_") +"__" +end.replace("/","_") +"celie_xiangxi" +'.txt',dir_new +"\\" +  start.replace("/","_") +"__" +end.replace("/","_")  +'_' +"--正收益买概率--" +str('%.2f'%(zhengshouyi_num / (zhengshouyi_num + fushouyi_num)))  +"--倍数--" +str('%.2f'%(total_shouyi))+"--正收益次数--" +str(zhengshouyi_num) +"--负收益次数--" +str(fushouyi_num)+'.txt')

return [total_shouyi,zhengshouyi_num / (zhengshouyi_num + fushouyi_num)]

if __name__ =='__main__':

print('start',time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

cur_dir = os.getcwd()# get current path

    folder_name ='result'

    dir_new = os.path.join(cur_dir, folder_name)

start = ['2016/09/01','2017/09/01','2018/09/01']

end = ['2017/12/31','2018/12/31','2019/12/31']

gupiaochichang = []

total_shouyi_gailv = []

shouyi_huizong = []

gailv_huizong = []

for iin range(len(start)):

total_shouyi_gailv.append(Haerzi(start[i],end[i]))

for iin range(len(total_shouyi_gailv)):

shouyi_huizong.append(total_shouyi_gailv[i][0])

gailv_huizong.append(total_shouyi_gailv[i][1])

#绘图

    matplotlib.rcParams['font.family'] ='SimHei'  # SimHei黑体

    matplotlib.rcParams['font.size'] =10

    dir_new = os.path.join(cur_dir, folder_name)

file_name = dir_new +r'/' +'shouyi'

    #收益图

    plt.subplots_adjust(hspace=0.5)

fig1 = plt.subplot(211)

fig1.set_title("收益")

# 设置坐标轴范围

    fig1.set_xlim(-1, 3)

fig1.set_ylim(0, 50)

# 设置坐标轴名称

    fig1.set_xlabel('日期')

fig1.set_ylabel('收益')

# 设置坐标轴刻度

    fig1.set_xticks = np.arange(-1, 4, 1)

for a, bin zip(end, shouyi_huizong):

fig1.text(a, b +0.1, '%.2f' % b, ha='center', va='bottom', color='red', fontsize=20)

fig1.plot(end, shouyi_huizong, color='blue', marker='o')

# 正收益概率图

    fig2 = plt.subplot(212)

fig2.set_title("收益概率")

# 设置坐标轴范围

    fig2.set_xlim(-1, 3)

fig2.set_ylim(0, 1.2)

# 设置坐标轴名称

    fig2.set_xlabel('日期')

fig2.set_ylabel('收益概率')

# 设置坐标轴刻度

    fig2.set_xticks = np.arange(-1, 4, 1)

for a, bin zip(end, gailv_huizong):

fig2.text(a, b +0.1, '%.2f' % b, ha='center', va='bottom', color='blue', fontsize=20)

fig2.plot(end, gailv_huizong, color='blue', marker='o')

plt.savefig(file_name, dpi=300)

print('end',time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

你可能感兴趣的:(哈尔兹法则策略量化四(继续优化买点,加入均线系统以及大盘指数))