-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGAinPLR.py
274 lines (239 loc) · 9.36 KB
/
GAinPLR.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
import math
import json
from datetime import datetime
import tushare as ts
#import numpy as np
import copy
from numpy import random
def culDistence(x1,y1,x2,y2,x3,y3):
A=y2-y1
B=x1-x2
C=x2*y1-x1*y2
dis=abs(A*x3+B*y3+C)/math.sqrt(A*A+B*B)
return dis
def a(x1,x2,L):
d=[]
for i in range(x1,x2):
d.append(i)
d.append(culDistence(x1,stockPrice[x1*2+1],x2,stockPrice[x2*2+1],i,stockPrice[i*2+1]))
# index=d.index(max(d))
if len(d)==0:
return
d1=[d[i] for i in range(1,len(d),2)] #不包含索引的list
maxD = max(d1)
if maxD<L:
return
else:
index=d[d.index(maxD)-1]
result.append(index)
a(x1,index,L)
a(index,x2,L)
class Gas():
#初始化一些变量
def __init__(self,popsize,chrosize,xrangemin,xrangemax):
self.popsize =popsize
self.chrosize =chrosize
self.xrangemin =xrangemin
self.xrangemax =xrangemax
self.crossrate =0.6 #交叉率
self.mutationrate =0.01 #变异率
#初始化种群
def initialpop(self):
pop = random.randint(0,2,size =(self.popsize,self.chrosize)) #pop为初始好的数据
return pop
#定义函数
def fun(self,x1,x2,L):
global result
result=[]
a(x1,x2,L)
result=[0]+sorted(result)+[int(len(stockPrice)/2)-1]
# 画图部分
# for i in range(0,len(result)-1):
# plt.plot([result[i],result[i+1]], [stockPrice[result[i]*2+1],stockPrice[result[i+1]*2+1]], 'r-')
# plt.show()
# 计算盈利率
profitRate = 1
for i in range(0,len(result)-1):
p1=stockPrice[result[i+1]*2+1]
p0=stockPrice[result[i]*2+1]
if p1-p0>0:
# profitRate *= (2*p1-p0)*(1-Fee)/p1
# 改进计算利润率算法
profitRate *= 1+((1-Fee)*p1-(1+Fee)*p0)/((1+Fee)*p0)
return profitRate
#适应度函数,由于我们所求的是最大值,所以可以用函数值代替适应度
def get_fitness(self,x1,x2,x):
fitness = []
for l in x:
fitness.append(self.fun(x1,x2,l))
return fitness
#输入参数为上一代的种群,和上一代种群的适应度列表
def selection(self,popsel,fitvalue):
new_fitvalue = []
totalfit = sum(fitvalue)
accumulator = 0.0
for val in fitvalue:
#对每一个适应度除以总适应度,然后累加,这样可以使
#适应度大的个体获得更大的比例空间。
new_val =(val/totalfit)
accumulator += new_val
new_fitvalue.append(accumulator)
ms = []
for i in range(self.popsize):
#随机生成0,1之间的随机数
ms.append(random.random())
ms.sort() #对随机数进行排序
fitin = 0
newin = 0
newpop = popsel
while newin < self.popsize:
#随机投掷,选择落入个体所占轮盘空间的个体
if(ms[newin] < new_fitvalue[fitin]):
newpop[newin] = popsel[fitin]
newin = newin + 1
else:
fitin = fitin + 1
#适应度大的个体会被选择的概率较大
#使得新种群中,会有重复的较优个体
pop = newpop
return pop
def crossover(self,pop):
for i in range(self.popsize-1):
#近邻个体交叉,若随机数小于交叉率
if(random.random()<self.crossrate):
#随机选择交叉点
singpoint =random.randint(0,self.chrosize)
temp1 = []
temp2 = []
#对个体进行切片,重组
temp1.extend(pop[i][0:singpoint])
temp1.extend(pop[i+1][singpoint:self.chrosize])
temp2.extend(pop[i+1][0:singpoint])
temp2.extend(pop[i][singpoint:self.chrosize])
pop[i]=temp1
pop[i+1]=temp2
return pop
def mutation(self,pop):
for i in range(self.popsize):
#反转变异,随机数小于变异率,进行变异
if (random.random()< self.mutationrate):
mpoint = random.randint(0,self.chrosize-1)
#将随机点上的基因进行反转。
if(pop[i][mpoint]==1):
pop[i][mpoint] = 0
else:
pop[mpoint] =1
return pop
def elitism(self,pop,popbest,nextbestfit,fitbest):
#输入参数为上一代最优个体,变异之后的种群,
#上一代的最优适应度,本代最优适应度。这些变量是在主函数中生成的。
if nextbestfit-fitbest <0:
#满足精英策略后,找到最差个体的索引,进行替换。
pop_worst =nextfitvalue.index(min(nextfitvalue))
pop[pop_worst] = popbest
return pop
#对十进制进行转换到求解空间中的数值
def get_declist(self,chroms):
step =(self.xrangemax - self.xrangemin)/float(2**self.chrosize-1)
self.chroms_declist =[]
for i in range(self.popsize):
chrom_dec =self.xrangemin+step*self.chromtodec(chroms[i])
self.chroms_declist.append(chrom_dec)
return self.chroms_declist
#将二进制数组转化为十进制
def chromtodec(self,chrom):
m = 1
r = 0
for i in range(self.chrosize):
r = r + m * chrom[i]
m = m * 2
return r #0011001111
if __name__ =='__main__':
stockPrice=[]
stockPrice1=[]
# L=1
Fee=0.001 #每笔交易手续费
# global result #点集
# result=[]
sns.set_style("whitegrid")
end = datetime.today() #开始时间结束时间,选取最近一年的数据
start = datetime(end.year,end.month-6,end.day)
end = str(end)[0:10]
start = str(start)[0:10]
stock = ts.get_hist_data('002253',start,end)#选取一支股票
stock.to_json('stock.json',orient='records')#转化为json格式
with open('stock.json', 'r') as f:
data = json.load(f)
# for p in data[:]:
# stockPrice.append(p['open'])
for p in range(len(data)-1,-1,-1): #调换顺序,使成为随时间增长变化的曲线
stockPrice1.append(data[p]['close'])
for p in range(0,len(stockPrice1)):
stockPrice.append(p)
stockPrice.append(stockPrice1[p])
# stock['close'].plot(legend=False ,figsize=(12,4)) #原画图
# plt.gcf().set_size_inches(12,4)
# plt.plot([stockPrice[i] for i in range(0,len(stockPrice),2)],[stockPrice[i] for i in range(1,len(stockPrice),2)],'b-')
#遗传算法部分
generation = 20 # 遗传代数
popsize=500 #每代的个体数
chrosize=9 #变量编码长度
xrangemin=1 #变量取值范围
xrangemax=5
#引入Gas类,传入参数:种群大小,编码长度,变量范围
mainGas =Gas(popsize,chrosize,xrangemin,xrangemax)
pop =mainGas.initialpop() #种群初始化
pop_best = [] #每代最优个体
for i in range(generation):
#在遗传代数内进行迭代
declist =mainGas.get_declist(pop)#解码
fitvalue =mainGas.get_fitness(0,int(len(stockPrice)/2)-1,declist)#适应度函数
#选择适应度函数最高个体
popbest = pop[fitvalue.index(max(fitvalue))]
#对popbest进行深复制,以为后面精英选择做准备
popbest =copy.deepcopy(popbest)
#最高适应度
fitbest = max(fitvalue)
#保存每代最高适应度值
pop_best.append(fitbest)
################################进行算子操作,并不断更新pop
mainGas.selection(pop,fitvalue) #选择
mainGas.crossover(pop) # 交叉
mainGas.mutation(pop) #变异
################################精英策略前的准备
#对变异之后的pop,求解最大适应度
nextdeclist = mainGas.get_declist(pop)
nextfitvalue =mainGas.get_fitness(0,int(len(stockPrice)/2)-1,nextdeclist)
nextbestfit = max(nextfitvalue)
################################精英策略
#比较深复制的个体适应度和变异之后的适应度
mainGas.elitism(pop,popbest,nextbestfit,fitbest)
t = [x for x in range(generation)]
s = pop_best
l=''
for i in list(popbest)[::-1]:
l += str(i)
q=xrangemin+int(l,2)*(xrangemax-xrangemin)/(2**chrosize-1)
print('最佳阈值:',round(q,2))
print('最大获利:',round(max(s),2))
p0=stockPrice[1]
p1=stockPrice[-1]
chiyou = ((1-Fee)*p1-(1+Fee)*p0)/((1+Fee)*p0)
print('持有获利:',round(chiyou,2))
#画遗传算法图
plt.subplot(211)
plt.plot(t,s)
#画分段线性图
plt.subplot(212)
plt.gcf().set_size_inches(13,10)
plt.plot([stockPrice[i] for i in range(0,len(stockPrice),2)],[stockPrice[i] for i in range(1,len(stockPrice),2)],'b-')
result=[]
a(0,int(len(stockPrice)/2)-1,q)
result=[0]+sorted(result)+[int(len(stockPrice)/2)-1]
for i in range(0,len(result)-1):
plt.plot([result[i],result[i+1]], [stockPrice[result[i]*2+1],stockPrice[result[i+1]*2+1]], 'r-')
plt.show()