2015年1月28日水曜日

遺伝的アルゴリズムでカブロボ制作⑦ 

前回までで遺伝的アルゴリズムの要素すべてを作成できました。
今回はこれらすべての要素を組み合わせて、遺伝子を選抜していこうと思います。
全体的な流れとしては、
遺伝子を初期化、評価、淘汰、突然変異もしくは交差を行い、
評価から交差までを繰り返します。

最初に元金として100000万円持たせていて、
これが300日で最も増加する遺伝子が最良のものとして選択します。

import random
import sys
from dataload_class import vstr2date
from dataload_class import dataload

def geanInit(popSize):
    #遺伝子の初期化
#    popSize = 10 #個体数
    geanLength = 10 #遺伝子長さ
    pop = []    #個体
    popGroup = []
    kaiGean = []    #買い遺伝子
    uriGean = []    #売り遺伝子
    enki = 0    #-1or1
    for i in range(popSize):
        for j in range(geanLength):
            enki = random.choice([-1,1])
            kaiGean.append(enki)
        for j in range(geanLength):
            enki = random.choice([-1,1])
            uriGean.append(enki)
        pop.append(list(kaiGean))
        pop.append(list(uriGean))
        kaiGean =[]
        uriGean = []
        popGroup.append(list(pop))
        pop =[]
#    print popGroup
    return popGroup

def predata_init():
    code = 1301
    data = dataload(code)
    data = data.loadfile()
    if data != 0:
      t = vstr2date(data)
#      print data[dataload.hajimene]
    return [t, data[dataload.hajimene]]

def negative2zero(num):
    if num<0:
        num = 0
    return num

def evalutionFunc(popGrope,popsize):
    stockPrice = [] #株価
    date = []   #日付
    date,stockPrice = predata_init()
#    print date,stockPrice
#    popGrope = [[[-1, 1, -1, -1, 1, -1, -1, 1, -1, 1], [1, -1, -1, 1, 1, -1, 1, 1, 1, 1]], [[1, 1, 1, 1, 1, -1, -1, 1, 1, 1], [1, 1, -1, 1, 1, 1, 1, 1, -1, -1]], [[1, 1, 1, -1, -1, -1, -1, -1, 1, 1], [-1, 1, 1, 1, -1, 1, -1, -1, 1, 1]], [[-1, 1, 1, 1, -1, -1, 1, 1, -1, -1], [-1, -1, -1, 1, 1, -1, 1, -1, -1, -1]], [[-1, -1, 1, -1, 1, -1, 1, 1, -1, 1], [1, 1, -1, -1, 1, 1, -1, 1, -1, -1]], [[-1, 1, -1, -1, 1, 1, 1, 1, 1, 1], [-1, 1, -1, 1, -1, 1, 1, 1, -1, 1]], [[1, 1, 1, 1, 1, 1, -1, 1, -1, -1], [1, -1, 1, 1, -1, 1, -1, -1, -1, -1]], [[1, -1, -1, -1, 1, -1, -1, -1, 1, -1], [1, -1, -1, 1, -1, -1, 1, -1, 1, 1]], [[-1, 1, 1, 1, -1, 1, -1, -1, 1, 1], [1, -1, -1, -1, -1, 1, -1, 1, 1, 1]], [[1, -1, 1, -1, -1, -1, 1, -1, -1, 1], [-1, -1, 1, 1, 1, 1, 1, -1, -1, 1]]]
    totalAssetsArry =[]
    popnum = 0
    for popnum in range(popsize):
#        print popGrope
#        print popnum
        pop = list(popGrope[popnum])
        kaiGean = pop[0]
        uriGean = pop[1]
        principal = 1000000 #元金(¥100万)
        holding = 0 #持ち株量
        #評価ループ
        lenStockprice = len(stockPrice)
    #    print lenStockprice
        fluctuationArry =[] #現在時間の評価配列を作る
        today = lenStockprice - 100
        agoArry =[0,1,2,3,5,8,13,21,35,56,89]
        n=0
        m=0
#        print "--------------------------------------------------"
#        print date[today]
        for j in range(300):
            todayPrice = stockPrice[today]
    #        print date[today]
    #        print todayPrice
            for i in range(10):
                n = agoArry[i]
                m = agoArry[i+1]
    #            print n,m
                ndayagoPrice = stockPrice[today + n]    #n日前の株価
                mdayagoPrice = stockPrice[today + m]    #m日前の株価
                changeValue =ndayagoPrice - mdayagoPrice
    #            print mdayagoPrice, date[today + m]
                if changeValue<0:
                    fluctuationArry.append(-1)#小さかったら評価配列に-1追加
                else:
                    fluctuationArry.append(1)
    #        print fluctuationArry
            #ある地点での評価に使う配列完成
            #評価配列と遺伝子の一致度を見る
    #        print kaiGean[7]
    #        print popGrope
            kaiPoint =(negative2zero(fluctuationArry[0]*kaiGean[0])*18)+\
                        (negative2zero(fluctuationArry[1]*kaiGean[1])*16)+\
                        (negative2zero(fluctuationArry[2]*kaiGean[2])*14)+\
                        (negative2zero(fluctuationArry[3]*kaiGean[3])*12)+\
                        (negative2zero(fluctuationArry[4]*kaiGean[4])*10)+\
                        (negative2zero(fluctuationArry[5]*kaiGean[5])*10)+\
                        (negative2zero(fluctuationArry[6]*kaiGean[6])*8)+\
                        (negative2zero(fluctuationArry[7]*kaiGean[7])*6)+\
                        (negative2zero(fluctuationArry[8]*kaiGean[8])*4)+\
                        (negative2zero(fluctuationArry[9]*kaiGean[9])*2)
#            print kaiPoint
            if kaiPoint> 40:
#                print principal,holding,todayPrice
                holding = holding+ principal /todayPrice
                principal = principal -(principal /todayPrice)*todayPrice
#                print principal,holding,todayPrice
#            print uriGean[7]
            uriPoint =(negative2zero(fluctuationArry[0]*uriGean[0])*18)+\
                        (negative2zero(fluctuationArry[1]*uriGean[1])*16)+\
                        (negative2zero(fluctuationArry[2]*uriGean[2])*14)+\
                        (negative2zero(fluctuationArry[3]*uriGean[3])*12)+\
                        (negative2zero(fluctuationArry[4]*uriGean[4])*10)+\
                        (negative2zero(fluctuationArry[5]*uriGean[5])*10)+\
                        (negative2zero(fluctuationArry[6]*uriGean[6])*8)+\
                        (negative2zero(fluctuationArry[7]*uriGean[7])*6)+\
                        (negative2zero(fluctuationArry[8]*uriGean[8])*4)+\
                        (negative2zero(fluctuationArry[9]*uriGean[9])*2)
            if uriPoint> 40:
    #            print "a",principal,holding
                principal = principal +holding*todayPrice
                holding = holding - holding
    #            print principal, holding
#            print kaiPoint,uriPoint,principal,holding
            fluctuationArry = []
            today = today -1    #日付を進める
        #評価ループ
        totalAssets = principal + holding* todayPrice
#        print totalAssets
#        print date[today]
        totalAssetsArry.append(totalAssets)
#    print totalAssetsArry
    return totalAssetsArry




def main():
#    maxiter = 1, 繰り返し数
#    maximize = True,    スコアを最大化
#    popsize = 50,   個体数
#    popnum = 10,    遺伝子数(長さ)
#    elite = 0.2,    生き残る遺伝子の割合
#    mutprob =0.2    突然変異のおこる確立
    maxiter = 10
    elite =0.2
    popsize =10
    mutprob=0.3
    popnum =10
    popGrope =[]

    #淘汰
    def selection():
        popScore = [(score[i],list(popGrope[i])) for i in range(popsize)]
        popScore.sort()
        popScore.reverse()
        print popScore[0][0]
        ranked = [v for (s,v) in popScore]
        return ranked[:topelite]

    # 突然変異
    popSelect = 0
    uriOrKai = 0
    preMutGean = 0
    afterMutEnki = 0
    afterMutGean = 0
    enkiSelect = 0
    def mutant():
        popSelect = random.SystemRandom().randint(0,len(popGrope)-1)
        uriOrKai = random.SystemRandom().randint(0,1)
        preMutGean = list(popGrope[popSelect][uriOrKai])
        afterMutEnki = random.choice([-1,1])
        enkiSelect = random.SystemRandom().randint(0,popnum-1)
        afterMutGean = preMutGean[:enkiSelect] + [afterMutEnki] +\
            preMutGean[enkiSelect+1:]
        afterMutPop = list(popGrope[popSelect])
        afterMutPop[uriOrKai] = afterMutGean
        popGrope.append(afterMutPop)
#        print preMutGean
#        print afterMutGean

     # 1点交叉 非推奨

    # 2点交叉
    uri = 0
    kai = 1
    kidPop =[uri,kai]
    #2点交差
    def twoPointCrossover(ma,fa):
        i, j = sorted(random.SystemRandom().sample(range(popnum),2))
        return random.SystemRandom().choice((ma[0:i] + fa[i:j] + ma[j:] , fa[0:i] + ma[i:j] + fa[j:]))

    # 一様交叉

    # 交叉アルゴリズムの選択
    crossover = twoPointCrossover
#    popGrope =[]
    #遺伝子初期化
    popGrope = geanInit(popsize)
#    print popGrope
    for k in range(maxiter):
        #メインループ
        #遺伝子評価
        score = evalutionFunc(popGrope,popsize)
        topelite = int(elite * popsize)
        popGrope = selection()  #淘汰
#        print popGrope
        while len(popGrope) < popsize:
            if random.SystemRandom().random() < mutprob:
                mutant()    #突然変異
        #        print popGrope[0]
        #        print popGrope[1]
        #        print popGrope[2]
            else:
                #交差
                #個体群から2匹抜き取る
                while 1:
                    matherPop = random.SystemRandom().randint(0,len(popGrope)-1)
                    fatherPop = random.SystemRandom().randint(0,len(popGrope)-1)
#                    print matherPop,fatherPop
                    if matherPop != fatherPop:
                       break
                #子供
                selectCrossOver = random.SystemRandom().randint(0,1)
                if selectCrossOver == 0:
                    #父母から1つずつ
                    while 1:
                        maOrFaUri = random.choice([matherPop,fatherPop])
                        maOrFaKai = random.choice([matherPop,fatherPop])
                        if maOrFaUri != maOrFaKai:
                            break
#                    print maOrFaUri,maOrFaKai
                    kidPop[uri] = list(popGrope[maOrFaUri][uri])
                    kidPop[kai] = list(popGrope[maOrFaKai][kai])
#                    print popGrope[maOrFaUri]
#                    print popGrope[maOrFaKai]
#                    print kidPop
                if selectCrossOver == 1:
                    #1つずつもらって交差あり
                    kidPop[uri] = crossover(list(popGrope[matherPop][uri]),list(popGrope[fatherPop][uri]))
                    kidPop[kai] = crossover(list(popGrope[matherPop][kai]),list(popGrope[fatherPop][kai]))
#                    print kidPop
                popGrope.append(kidPop)

#        print popGrope
        print "------------------------------------------------------",k
        #メインループ
        #score = evalutionFunc(popGrope,popsize)
        #print score
    score = evalutionFunc(popGrope,popsize)
    print score
    topelite = int(elite * popsize)
    popGrope = selection()
    print popGrope[0]


if __name__ == '__main__':
    main()

以上になります。
これで、遺伝子を選択するプログラムが出来ました。
参考までに実行してみたところ、
1000000円が1443537円まで増加しました。
ご使用になる方は自己責任でお願いします。

次回はこの遺伝子を使って長期間での変化を見ていこうと思います。

0 件のコメント:

コメントを投稿