2015年1月30日金曜日

カブロボの実行-遺伝的アルゴリズム

前回完成しました遺伝的アルゴリズムで作成した株ロボをいよいよ実行してみようと思います。
前回までで、遺伝子の抽出までが完成しました。
今回は抽出した遺伝子を使って、その後の推移を見ていこうと思います。
今回新しく書いたプログラムは、評価関数と同様のものを、より長期間回すようなプログラムです。
テストとして、株式1301コードのデータを使いました。

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

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 geanSelection(maxiter,elite,popsize,mutprob,popnum):
    #    maxiter = 1, 繰り返し数
#    maximize = True,    スコアを最大化
#    popsize = 50,   個体数
#    popnum = 10,    遺伝子数(長さ)
#    elite = 0.2,    生き残る遺伝子の割合
#    mutprob =0.2    突然変異のおこる確立
##    maxiter = 100
##    elite =0.2
##    popsize =50
##    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()
    return popGrope[0]


def main():
    maxiter = 100
    elite =0.1
    popsize =100
    mutprob=0.3
    popnum =10
    selectedPop = geanSelection(maxiter,elite,popsize,mutprob,popnum)
    print selectedPop

    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

#        print popGrope
#        print popnum
    pop = list(selectedPop)
    kaiGean = pop[0]
    uriGean = pop[1]
    principal = 1000000 #元金(¥100万)
    holding = 0 #持ち株量
    principalStck =[]
    holdingStck =[]
    totalAssetsStck =[]

    #評価ループ
    lenStockprice = len(stockPrice)
#    print lenStockprice
    fluctuationArry =[] #現在時間の評価配列を作る
    today = lenStockprice - 400
    agoArry =[0,1,2,3,5,8,13,21,35,56,89]
    n=0
    m=0
#        print "--------------------------------------------------"
#        print date[today]
    for j in range(lenStockprice-400):
        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 principal,holding
#        totalAssets = principal + holding* todayPrice
#        totalAssetsStck.append(totalAssets)
        principalStck.append(principal)
#        holdingStck.append(holding)
        fluctuationArry = []
        today = today -1    #日付を進める
#        print today
    #評価ループ
    totalAssets = principal + holding* todayPrice
#        print totalAssets
#        print date[today]
#    totalAssetsArry.append(totalAssets)
    print totalAssetsArry
    pylab.plot(principalStck)
    pylab.show()

#    return totalAssetsArry

if __name__ == '__main__':
    main()
実行結果は運がいいと、
(縦軸が資金で横軸が時間です。)
100万円が1200万円くらいになりました。
遺伝的アルゴリズムすごいですね。
ただ、長期的に見過ぎな気もしますのでそこが改善点ですかね。
また、他の銘柄だと全くダメなときもあります。
例えば2712(スターバックス)なんかは
うまくいくと、
うまくいかないと、
この辺を調節するにはいろいろな人工知能の勉強をしないといけませんかね。
改善点としては、閾値の最適化や、現在は売り買いで全財産を一気に使っているので、
売り買いする量も調整していきたいと思います。
また、遺伝子の重み付けのやり方ももっといい方法があると思いますので、
そこも改善したいと思います。

と、改善することだらけですが、
これで遺伝的アルゴリズムを使ったコードが完成しましたので、
次回からはニューラルネットワークで作ってみようかなと思います。

0 件のコメント:

コメントを投稿