繁簡切換您正在訪問的是FX168財經網,本網站所提供的內容及信息均遵守中華人民共和國香港特別行政區當地法律法規。

FX168财经网>人物频道>帖子

基金智能定投法: 均线偏离法——遗传算法寻优

作者/dfdcdvdsa 2019-09-29 22:00 0 来源: FX168财经网人物频道

均线偏离法测试(OPT)

# 导入需要的程序包
import pandas as pd
import seaborn as sns
import random as rand
from datetime import datetime
SECURITY ='000001.XSHG'    #000001.XSHG  上证综指           #000300.XSHG 沪深300
AIP_FUND ='510210.XSHG'    #510210.XSHG #富国上证综指ETF    #159919.XSHE  #嘉实沪深300ETF 开始日期 2012-05-28
START_DATE='2005-04-09'    #取数的开始日期,上证综指不能早于'2005-01-05',沪深300不能早2005-04-08
END_DATE='2016-03-31'      #取数、测算的结束日期
START_CAL_DATE='2012-06-01'    #测算起始日期
STD_AMOUNT =100            #基准定投金额

#GA参数
PSIZE=20    #种群规模
TSIZE=5    # 锦标赛成员规模
TERMINAL=10    #迭代代数
PC=0.95    #交叉比率
PM=0.2    #变异比率
ALPH=1    #适配值函数参数
BETA=10
# 获取指数历史数据
security_data=get_price(SECURITY,START_DATE,END_DATE,fields=['price','close'])  #跟踪的指数
aip_fund_data=get_price(AIP_FUND,START_CAL_DATE,END_DATE,fields=['price'])    #定投的基金
# 种群初始化
class Population(object):
    def __init__(self,chromosome,amount=0.0,quantity=0.0,nav=0.0,fitness=0.0):
        self.chromosome = chromosome
        self.amount = amount
        self.quantity=quantity
        self.nav=nav
        self.fitness=fitness
popu=[Population(chromosome=[random.randint(0,4),random.randint(0,3),random.randint(0,3)]) for i in range(PSIZE)]
#第1段表示均线类型,第2段表示偏离度,第3段表示级差。

#获取START_CAL_DATE在security_data中的index
cal_date=pd.DatetimeIndex([datetime.strptime(START_CAL_DATE,'%Y-%m-%d')])[0]
i=0
index=-1
while (i<len(security_data)):
    if(security_data.index[i]>=cal_date):
        index=i
        break
    else:
        i+=1
if(index==-1):
    print('开始测算日期录入错误')
    sys.exit()

# 求某index的num日均线值
def mav(security_data,index,num):
    if(index-num<0):
        print('现有数据不足以计算此均值,最早日期为: ',security_data.index[0],'超出天数为: ',num-index)
        sys.exit()
    j=index-1
    sumv=0.0
    while (j>=index-num and j>=0):
        sumv=sumv+security_data.iloc[j][1]    #temp_security.iloc[j][0] 表示price;temp_security.iloc[j][1] 表示close
        j=j-1 
    mav=sumv/num
    return mav
# 解码函数
def decode(p=0,size=1):    #p:起始个体index    size:解码数量
    temp_p=p
    #检查录入的均线、偏离度、级差是否正确
    if(popu[temp_p].chromosome[2]>2):
        print('编码第3位:',popu[2],' 超出级差取值范围')
        sys.exit()
    if(popu[temp_p].chromosome[1]>2):
        print('编码第2位:',popu[1],' 超出偏离度取值范围')
        sys.exit()
    if(popu[temp_p].chromosome[0]>4):
        print('编码第1位:',popu[0],' 超出均线种类取值范围')
        sys.exit()

    while(temp_p<p+size):
        fd_index=index
        #计算START_CAL_DATE日个体编码对应的均线值
        if(popu[temp_p].chromosome[0]==0):
            mavg=mav(security_data,fd_index,120)
            #print('使用120均线')
        elif(popu[temp_p].chromosome[0]==1):
            mavg=mav(security_data,fd_index,180)
            #print('使用180均线')
        elif(popu[temp_p].chromosome[0]==2):
            mavg=mav(security_data,fd_index,250)
            #print('使用250均线')            
        elif(popu[temp_p].chromosome[0]==3):
            mavg=mav(security_data,fd_index,500)
            #print('使用180均线')
        elif(popu[temp_p].chromosome[0]==4):
            mavg=mav(security_data,fd_index,2426)           #10年均线按2426个工作日算(基于2005-1-5到2015-1-4计算得到)
            #print('使用10年均线')
        else:
            sys.exit()
        aip_index=0
        popu[temp_p].amount=0.0
        popu[temp_p].quantity=0.0
        popu[temp_p].nav=0.0
        popu[temp_p].fitness=0.0
        while(fd_index<len(security_data)):
        #0:广发 (-n,-40),[-40,-30),[-30,-20),[-20,-10),[-10,-5),[-5,0),(0,15],(15,50],(50,100],(100,n)
            if(popu[temp_p].chromosome[1]==0):
                rod=(security_data.iloc[fd_index][1]-mavg)*100/mavg         #security_data.iloc[j][1] 表示close,用close计算偏离率
                if(rod<-40):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*6))
                elif(rod<-30):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*5))
                elif(rod<-20):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*4))
                elif(rod<-10):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*3))                    
                elif(rod<-5):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*2)) 
                elif(rod<0):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*1))
                elif(rod<=15):
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.1*1))
                elif(rod<=50):
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.1*2))                                      
                elif(rod<=100):
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.1*3))    
                else:
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.1*4))

                popu[temp_p].amount += in_amount
                popu[temp_p].quantity += in_amount/aip_fund_data.iloc[aip_index][0]
                popu[temp_p].nav = popu[temp_p].amount/popu[temp_p].quantity
                            
                '''print('日期: ',aip_fund_data.index[aip_index],' 指数收盘价: ',security_data.iloc[fd_index][1],' 指数均值: ',mavg,' 偏离率:',rod,\
                    ' 基金净值: ',aip_fund_data.iloc[aip_index][0],' 购买金额: ',in_amount,' 总金额: ',\
                     pop[temp_p].amount,' 总数量: ',pop[temp_p].quantity,' 成本净值: ',pop[temp_p].nav)'''
            #1: 富国 (-n,-45),[-45,-35),[-35,-25),[-25,-15),[-15,-5),[-5,5),[5,20),[20,35),[35,50),[50,n)
            elif(popu[temp_p].chromosome[1]==1):
                rod=(security_data.iloc[fd_index][1]-mavg)*100/mavg
                if(rod<-45):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*5))
                elif(rod<-35):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*4))
                elif(rod<-25):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*3))
                elif(rod<-15):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*2))
                elif(rod<-5):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*1))                    
                elif(rod<5):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1*0))      
                elif(rod<20):
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.05*1))             
                elif(rod<35):
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.05*2))                       
                elif(rod<50):
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.05*3))                               
                else:
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.05*4))
                popu[temp_p].amount += in_amount
                popu[temp_p].quantity += in_amount/aip_fund_data.iloc[aip_index][0]
                popu[temp_p].nav = popu[temp_p].amount/popu[temp_p].quantity
                '''print('日期: ',aip_fund_data.index[aip_index],' 指数收盘价: ',security_data.iloc[fd_index][1],' 指数均值: ',mavg,' 偏离率:',rod,\
                    ' 基金净值: ',aip_fund_data.iloc[aip_index][0],' 购买金额: ',in_amount,' 总金额: ',\
                     pop[temp_p].amount,' 总数量: ',pop[temp_p].quantity,' 成本净值: ',pop[temp_p].nav) '''                   
            #2: 博时 price/avg<=0.9,0.9<price/avg<=1.1,price/avg>=1.1
            elif(popu[temp_p].chromosome[1]==2):
                rod=security_data.iloc[fd_index][1]/mavg
                if(rod<=0.9):
                    in_amount=(STD_AMOUNT*(1+(popu[temp_p].chromosome[2]+1)*0.1))
                elif(rod<1.1):
                    in_amount=STD_AMOUNT
                else:
                    in_amount=(STD_AMOUNT*(1-(popu[temp_p].chromosome[2]+1)*0.1))
                popu[temp_p].amount += in_amount
                popu[temp_p].quantity += in_amount/aip_fund_data.iloc[aip_index][0]
                popu[temp_p].nav = popu[temp_p].amount/popu[temp_p].quantity
                '''print('日期: ',aip_fund_data.index[aip_index],' 指数收盘价: ',security_data.iloc[fd_index][1],' 指数均值: ',mavg,' 偏离率:',rod,\
                    ' 基金净值: ',aip_fund_data.iloc[aip_index][0],' 购买金额: ',in_amount,' 总金额: ',\
                     pop[temp_p].amount,' 总数量: ',pop[temp_p].quantity,' 成本净值: ',pop[temp_p].nav) '''
            
            if(fd_index==(len(security_data)-1)):
                #popu[temp_p].fitness=(aip_fund_data.iloc[aip_index][0]-popu[temp_p].nav)*pop[temp_p].quantity
                popu[temp_p].fitness=ALPH*exp(BETA*(aip_fund_data.iloc[aip_index][0]*popu[temp_p].quantity)/popu[temp_p].amount)
                #popu[temp_p].fitness=(aip_fund_data.iloc[aip_index][0]*popu[temp_p].quantity)/popu[temp_p].amount
            fd_index+=1
            aip_index+=1
        temp_p=temp_p+1
# 选择算子函数(使用轮盘赌的方式从父代染色体中选择)
#import pdb
def select(size,sumfit):    #size:当前的种群规模
    sumfit=sumfit
    #pdb.set_trace()
    temp_popu=[Population(chromosome=[]) for i in range(PSIZE)]
    p=0
    while(p < PSIZE):
        sv=random.random()*sumfit[size-1]
        #print(' sv: ',sv,' total_sumfit: ',sumfit[size-1])
        sid = 0
        while (sid<size):
            if(sumfit[sid] > sv):
                #print(' sumfit[sid]: ',sumfit[sid],' sid: ',sid)
                temp_popu[p]=popu[sid]
                break
            else:
                sid+=1
        p+=1
    #pdb.set_trace()
    q=0
    while(q<size):
        if(q<PSIZE):
            popu[q]=temp_popu[q]
        else:
            popu.pop()    #去掉多余的个体
        #print(pop[q].chromosome,' ',pop[q].fitness)
        q+=1
# 交叉算子函数(使用一段式)
#import pdb
def crossover(size):
    pop_size=size
    p=0
    while(p<PSIZE):     #运行PSIZE次,总交叉次数为PSIZE*PC
        if(random.random()<PC):
            #创建锦标赛群体
            #pdb.set_trace()
           
            crs_pop=[int(random.random()*PSIZE) for i in range(TSIZE)]
            
            #pdb.set_trace()
            max_v=-99999999999999999999999999999999999999999999999999999999999
            max1=-1
            for j in crs_pop:
                if(popu[j].fitness>max_v):
                    max1=j
            crs_pop.remove(max1)
            max_v=-99999999999999999999999999999999999999999999999999999999999
            max2=-1
            for j in crs_pop:
                if(popu[j].fitness>max_v):
                    max2=j
            
            #计算交叉位置,开始交叉
            crs_point=int(random.random()*(len(popu[0].chromosome)-1))
            #pdb.set_trace()
            
            temp_chr1=[]
            temp_chr2=[]
            ci=0
            while (ci<len(popu[0].chromosome)):
                if(ci<crs_point):
                    temp_chr1.append(popu[max1].chromosome[ci])
                    temp_chr2.append(popu[max2].chromosome[ci])
                else:
                    temp_chr1.append(popu[max2].chromosome[ci])
                    temp_chr2.append(popu[max1].chromosome[ci])
                ci+=1
            
            temp_pop1=Population(chromosome=temp_chr1)
            temp_pop2=Population(chromosome=temp_chr2)
            popu.append(temp_pop1)
            popu.append(temp_pop2)
            pop_size+=2
        p+=1
    return pop_size
# 变异算子函数
#import pdb
def mutation(size):
    pop_size=size
    i=0
    while (i<PSIZE):
        #pdb.set_trace()
        temp_chr=[]

        mutated=0
        j=0
        while(j<len(popu[i].chromosome)):
            random_p = random.random()
            if(random_p<PM and j == 0):
                temp_chr.append(random.randint(0,4))
                mutated=1
                j+=1
            elif(random_p<PM and j == 1):
                temp_chr.append(random.randint(0,3))
                mutated=1
                j+=1
            elif(random_p<PM and j == 2):
                temp_chr.append(random.randint(0,3))
                mutated=1
                j+=1
            else:
                temp_chr.append(popu[i].chromosome[j])
                j+=1
        i+=1
        if(mutated==1):
            temp_pop=Population(chromosome=temp_chr)
            popu.append(temp_pop)
            pop_size+=1
    return pop_size        
def GA_MAIN():
    accumulate_income=[]
    decode(0,PSIZE)
    
    print('Initail')
    max_ini_fit=popu[0].fitness
    max_ini_id=0
    

    for p0 in range(PSIZE):
    # 显示种群全部个体
    #    print('id',p0,'chromosome: ',popu[p0].chromosome,' amount: ',popu[p0].amount,' quantity: ',popu[p0].quantity,\
    #        ' nav: ',popu[p0].nav,' fitness: ',popu[p0].fitness)
    #显示种群最优个体
        if(popu[p0].fitness>max_ini_fit):
            max_ini_fit=popu[p0].fitness
            max_ini_id=p0
    best_fit=popu[max_ini_id].fitness
    best_chr=popu[max_ini_id].chromosome
    print('id',max_ini_id,'chromosome: ',popu[max_ini_id].chromosome,' amount: ',popu[max_ini_id].amount,' quantity: ',\
          popu[max_ini_id].quantity,' nav: ',popu[max_ini_id].nav,' fitness: ',popu[max_ini_id].fitness)
    
    accumulate_income.append(100*(aip_fund_data.iloc[len(aip_fund_data)-1][0]*popu[max_ini_id].quantity)/popu[max_ini_id].amount-1)
    
    for runtime in range(TERMINAL):
        pp=crossover(PSIZE)
        
    #显示交叉算子处理后的种群
    #    print('after crossover')
    #    for p1 in range(pp):
    #        print('id',p1,'chromosome: ',popu[p1].chromosome,' amount: ',popu[p1].amount,' quantity: ',popu[p1].quantity,\
    #              ' nav: ',popu[p1].nav,' fitness: ',popu[p1].fitness)

        pp=mutation(pp)
    #显示变异算子处理后的种群
    #    print('after mutation')
    #    for p2 in range(pp):
    #        print('id',p2,'chromosome: ',popu[p2].chromosome,' amount: ',popu[p2].amount,' quantity: ',popu[p2].quantity,\
    #              ' nav: ',popu[p2].nav,' fitness: ',popu[p2].fitness)

        decode(PSIZE,pp-PSIZE)
    #解码种群所有个体
    #    print('after decode')
    #    for p3 in range(pp):
    #        print('id',p3,'chromosome: ',popu[p3].chromosome,' amount: ',popu[p3].amount,' quantity: ',popu[p3].quantity,\
    #              ' nav: ',popu[p3].nav,' fitness: ',popu[p3].fitness)

        #计算个体的sumfit
        sumfit=[]
        sumi=0.0
        si=0
        while(si<pp):
            sumi+=popu[si].fitness
            sumfit.append(sumi)
            si+=1
            
        select(pp,sumfit)
        
        print('Iteration: ',runtime)
        max_ini_fit=popu[0].fitness
        max_ini_id=0

        for p5 in range(len(popu)):
        # 显示种群全部个体
        #    print('id',p5,'chromosome: ',popu[p5].chromosome,' amount: ',popu[p5].amount,' quantity: ',popu[p5].quantity,\
        #          ' nav: ',popu[p5].nav,' fitness: ',popu[p5].fitness)
        #显示种群最优个体         
            if(popu[p5].fitness>max_ini_fit):
                max_ini_fit=popu[p5].fitness
                max_ini_id=p5
        if(best_fit<popu[max_ini_id].fitness):
            best_fit=popu[max_ini_id].fitness
            best_chr=popu[max_ini_id].chromosome
        print('id',max_ini_id,'chromosome: ',popu[max_ini_id].chromosome,' amount: ',popu[max_ini_id].amount,' quantity: ',\
              popu[max_ini_id].quantity,' nav: ',popu[max_ini_id].nav,' fitness: ',popu[max_ini_id].fitness)
        accumulate_income.append(100*(aip_fund_data.iloc[len(aip_fund_data)-1][0]*popu[max_ini_id].quantity)/popu[max_ini_id].amount-1)
    print(' best_chr: ',best_chr,' best_fit: ',best_fit,' accumulate_income: ',accumulate_income)
    
    #设置横坐标和纵坐标的名称
    plt.xlabel('Iteration')
    plt.ylabel('Accumulate_income')
    # 图的标题
    plt.title('Accumulate income of each GA iteration')
    # 定义线条
    line1 = plt.plot(accumulate_income)
    plt.setp(line1, color='r', linewidth=2.0,label='GA')
    plt.legend()

GA_MAIN()
Initail
id 15 chromosome:  [2, 0, 2]  amount:  117500.0  quantity:  50641.0163359  nav:  2.3202535909  fitness:  1221645.61465
Iteration:  0
id 18 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  1
id 6 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  2
id 0 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  3
id 10 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  4
id 1 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  5
id 1 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  6
id 0 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  7
id 0 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  8
id 0 chromosome:  [1, 0, 2]  amount:  108200.0  quantity:  46991.3927298  nav:  2.30254933328  fitness:  1360653.82046
Iteration:  9
id 3 chromosome:  [0, 0, 2]  amount:  102800.0  quantity:  44730.1949072  nav:  2.29822383321  fitness:  1397307.55286
 best_chr:  [0, 0, 2]  best_fit:  1397307.55286  accumulate_income:  [139.15709372277004, 140.23475892530581, 140.23475892530581, 140.23475892530581, 140.23475892530581, 140.23475892530581, 140.23475892530581, 140.23475892530581, 140.23475892530581, 140.23475892530581, 140.50057766377631]
分享到:
举报财经168客户端下载

全部回复

0/140

投稿 您想发表你的观点和看法?

更多人气分析师

  • 张亦巧

    人气2144文章4145粉丝45

    暂无个人简介信息

  • 梁孟梵

    人气2152文章3177粉丝39

    qq:2294906466 了解群指导添加微信mfmacd

  • 指导老师

    人气1856文章4423粉丝52

    暂无个人简介信息

  • 李冉晴

    人气2296文章3821粉丝34

    李冉晴,专业现贷实盘分析师。

  • 刘钥钥1

    人气2016文章3119粉丝34

    专业从事现货黄金、现货白银模似实盘操作分析指导

  • 张迎妤

    人气1896文章3305粉丝34

    个人专注于行情技术分析,消息面解读剖析,给予您第一时间方向...

  • 金泰铬J

    人气2320文章3925粉丝51

    投资问答解咨询金泰铬V/信tgtg67即可获取每日的实时资讯、行情...

  • 金算盘

    人气2696文章7761粉丝125

    高级分析师,混过名校,厮杀于股市和期货、证券市场多年,专注...

  • 金帝财神

    人气4728文章8329粉丝118

    本文由资深分析师金帝财神微信:934295330,指导黄金,白银,...