Wednesday, July 11, 2018

Pyhton 股票回測與MACD(二)

加入一些咚咚





左右對照圖
睡醒看到這個真的不是很開心rrr

以後要盯盤的時候,看了文字圖形看不慣吧?,我們來加入一些新元素,畫圖均線,標註買賣點好了,回測,績效等等介面化等等,我們可以看,近期內一定要完成ai,先完成專題在讀研究所?



# -*- coding: utf-8 -*-
"""
Created on Wed Dec 20 17:46:15 2017
@author: user
"""
from tkinter import *
from tkinter import messagebox
import tkinter as tk
import random
from tkinter import HORIZONTAL
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
import pandas as pd
import csv
import talib
import os
import time
import matplotlib.pyplot as plt
from mpl_finance import candlestick_ohlc
from mpl_finance import volume_overlay3
import matplotlib.dates as dates
from datetime import datetime
plt.rcParams['font.sans-serif'] = ['DFKai-sb']
plt.rcParams['font.family']='sans-serif'
#技術指標
def get_MACD():
MACD = talib.MACD(np.array(close),
fastperiod=12, slowperiod=26, signalperiod=9)
return [float(x) for x in MACD [1]]
def get_DIF():
DIF=[]
EMA12=talib.EMA(np.array(close), timeperiod=12)
EMA26=talib.EMA(np.array(close), timeperiod=26)
for tmp in range(0,len(EMA12)):
DIF.append(float(EMA12[tmp]-EMA26[tmp]))
return DIF
def get_OSC(macd,dif):
OSC=[]
for tmp in range(0,len(macd),1):
OSC.append(float(macd[tmp]-dif[tmp]))
return OSC
data_list = []
data_list2 = []
buy_list=[]
sell_list=[]
num_48 = ["1216統一"]
df=pd.DataFrame()
df2=pd.DataFrame(num_48)
for iii in num_48:
path_str=os.path.join("C:\\","Users","x2132","OneDrive","桌面","History_data",iii)
path_str=path_str+'.csv'
print (path_str)
#收盤
with open(path_str,'r') as c:
reader=csv.DictReader(c)
c=[row["收盤"] for row in reader] #要導入的列
#開盤
with open(path_str,'r') as o:
reader=csv.DictReader(o)
o=[row["開盤"] for row in reader] #要導入的列
#最高
with open(path_str,'r') as h:
reader=csv.DictReader(h)
h=[row["最高"] for row in reader] #要導入的列
#最低
with open(path_str,'r') as l:
reader=csv.DictReader(l)
l=[row["最低"] for row in reader] #要導入的列
#成交量
with open(path_str,'r') as v:
reader=csv.DictReader(v)
v=[row["成交量"] for row in reader] #要導入的列
#日期
with open(path_str,'r') as d:
reader=csv.DictReader(d)
d=[row["日期"] for row in reader] #要導入的列
ope = [float(x) for x in o]
close = [float(x) for x in c]
high = [float(x) for x in h]
low = [float(x) for x in l]
vol = [float(x)*0.0001 for x in v]
date =d
date_ex=[]
date.reverse()
low.reverse()
high.reverse()
close.reverse()
ope.reverse()
for x in range(0,len(ope),1):
#datess =dates.date2num(d[x])
#print (datetime.datetime(2017, 3, 13))
#print (dates.date2num(datetime.datetime(2017, 3, 13, 12, 0)))
#print (datetime.datetime(2017, 3, 13, 12, 0))
t = d[x].replace('/','-')
#print ((dates.date2num(datetime.strptime(t, '%Y-%m-%d'))))
# (type(datetime.datetime(2017, 3, 13, 12, 0)))
#print (type(dates.date2num(datetime.datetime(2017, 3, 13, 12, 0))))
#print(dates.date2num(datetime.datetime(2017, 3, 13, 12, 0)))
datas = (dates.date2num(datetime.strptime(t, '%Y-%m-%d')) , ope[x], high[x], low[x],close[x])
datas2 = (dates.date2num(datetime.strptime(t, '%Y-%m-%d')) , ope[x], high[x], low[x],close[x],vol[x])
date_ex.append(dates.date2num(datetime.strptime(t, '%Y-%m-%d')))
data_list.append(datas)
data_list2.append(datas2)
MACD=get_MACD()
DIF=get_DIF()
OSC=get_OSC(MACD,DIF)
#交易策略
start=0
end=len(data_list)
win=[]
win_con=[0]
los_con=[0]
buy_data=[]
self_data=[]
buy_date=[]
self_date=[]
star=100000 #一開始的錢
price=100000
handle=0 #持有股數
ex_handle=1 #持有股數上限
re_handle=0 #實際持有
for tmp in range(12,len(DIF),1):
if((tmp+1<len(DIF)) and tmp>start and tmp<end ):
print (tmp)
if(OSC[tmp]>=0 and price >= (ex_handle*close[tmp]*1000) ):
handle= handle+ex_handle*1000
re_handle=re_handle+ex_handle
fin_price=price-(ex_handle*ope[tmp+1])*1000 #1=1000
print ('買進日期',date[tmp+1],'開盤價',ope[tmp+1],'支出',(ex_handle*ope[tmp+1])*1000,'結算金額',fin_price,'持有股數',handle,'持有張數',re_handle)
tmp_str='買進日期',date[tmp+1],'開盤價',ope[tmp+1],'支出',(ex_handle*ope[tmp+1])*1000,'結算金額',fin_price,'持有股數',handle,'持有張數',re_handle
buy_data.append(tmp_str)
buy_list.append(data_list[tmp+1])
price= fin_price
elif (OSC[tmp]<0 and re_handle >=1 ):
fin_price=price+(re_handle*close[tmp])*1000
handle=0
re_handle=0
print ('賣出日期',date[tmp],'收盤價',close[tmp],'結算金額',fin_price,'持有股數',handle,'持有張數',re_handle)
tmp_str='賣出日期',date[tmp],'收盤價',close[tmp],'結算金額',fin_price,'持有股數',handle,'持有張數',re_handle
sell_list.append(data_list[tmp])
self_data.append(tmp_str)
price= fin_price
if (handle>0):#強制平倉
fin_price+= (close[len(close)-1]*handle)
handle=0
re_handle=0
print ('強制平倉 賣出日期',date[len(close)-1],'收盤價',close[len(close)-1],'結算金額',fin_price,'持有股數',handle,'持有張數',re_handle)
#回測績效 - 交易次數
count=0
loss=0
for a,b in zip (buy_data[:],self_data[:]):
buy_date.append(a[3])
self_date.append(b[3])
if buy_date[0]<self_date[0]:
count+=1
else:
loss+=1
del buy_date[0]
del self_date[0]
for a,b in zip (buy_data[:],self_data[:]):
buy_date.append(a[3])
self_date.append(b[3])
if len(buy_date)>0:
z=(self_date[0]-buy_date[0])/buy_date[0]
if z>0:
win_con.append(z)
elif z<0:
los_con.append(z)
del buy_date[0]
del self_date[0]
print ('交易紀錄')
print ('-----------------------------------')
for tmp in buy_data:
print (tmp)
for tmp in self_data:
print (tmp)
wp=int(fin_price-star)
buy=len(buy_data)
sel=len(self_data)
total_trade=sum((len(buy_data),len(self_data)))
win_rate=round(count/sum((len(buy_data),len(self_data)))*100,2)
retur=round(((fin_price-star)/star)*100,2)
ave_retur=round((((fin_price-star)/star))/(sum((len(buy_data),len(self_data))))*100,4)
win_num=count
los_num=loss
max_win=round(max(win_con),2)
min_los=round(min(los_con),2)
data={"獲利金額":[wp],"買次數":[buy],"賣次數":[sel],"總交易次數":[total_trade],"勝率":[win_rate],"報酬率":[retur],"平均報酬率":[ave_retur],"獲利次數":[win_num],"虧損次數":[los_num],"最大獲利率":[max_win],"最大虧損率":[min_los]}
df=df.append(pd.DataFrame(data),ignore_index=True)
df.insert(0,'股票代號',df2)
df.to_csv("MACD.KPI.csv")
print ('獲利金額:',(int(fin_price-star)))
print ('交易次數 買/賣:',len(buy_data),'/',len(self_data))
print ('總交易次數:',sum((len(buy_data),len(self_data))))
print ('勝率:%5.2f'%(count/sum((len(buy_data),len(self_data)))*100),"%")
print ('報酬率:',round(((fin_price-star)/star)*100,2))
print ('報酬率:%5.2f'%(((fin_price-star)/star)*100),"%")
print ('平均報酬率',round((((fin_price-star)/star))/(sum((len(buy_data),len(self_data))))*100,4),"%")
print("獲勝次數:",count)
print("虧損次數:",loss)
print("最大獲利率:",round(max(win_con),2),"%")
print("最大虧損率:",round(min(los_con),2),"%")
# tmp2=10
# print (str(tmp2))
# tmp =type(tmp2)
# fig, ax = plt.subplots()
# print (fig)
# print (ax)
# fig.subplots_adjust(bottom=0.2)
# # 设置X轴刻度为日期时间
# #data_list.reverse()
# ax.xaxis_date()
# plt.xticks(rotation=45)
# plt.yticks()
# plt.title("k線圖")
# plt.xlabel("時間")
# plt.ylabel("股價")
# #print (len(data_list))
# candlestick_ohlc(ax, data_list[1000:2000], width=0.5, colorup='r', colordown='g')
# for x in range(0,len(buy_list),1):
# ax.annotate('', xy=(buy_list[x][0],buy_list[x][1]), xytext=(-15, -27),
# textcoords='offset points', ha="center",
# arrowprops=dict(facecolor='black', color='red',width=1),
# )
# for x in range(0,len(sell_list),1):
# ax.annotate('', xy=(sell_list[x][0],sell_list[x][1]), xytext=(-17, 20),
# textcoords='offset points', ha="center",
# arrowprops=dict(facecolor='black', color='green',width=1),
# )
# #print('hello')
# pro_fit='獲利金額:'+str((int(fin_price-star)))
# buy_count='交易次數 買/賣:'+str(len(buy_data))+'/'+str(len(self_data))
# plt.figtext(0.1,0.92,pro_fit+'\n'+buy_count,color='black')
# #plt.grid()
# plt.savefig("filename.png")
# #plt.show()
# print (buy_list[x][1])
# # print (buy_list)
# # print (MACD[500])
# # print (start)
# # print (end)
#畫圖區~~~~~~~~~
def show_info():
str_tmp='初始金額:'+str((int(star)))+"\n"+'獲利金額:'+str((int(fin_price-star)))+"\n"+'總收入金額:'+str((int(fin_price)))+"\n"+'交易次數 買/賣:'+str(len(buy_data))+'/'+str(len(self_data))+"\n"+'總交易次數:'+str(sum((len(buy_data),len(self_data))))+"\n"+'勝率:'+str((count/sum((len(buy_data),len(self_data)))*100))+'%'+"\n"+'報酬率:'+str(((fin_price-star)/star)*100)+'%'+"\n"+'平均報酬率:'+str(round((((fin_price-star)/star))/(sum((len(buy_data),len(self_data))))*100,4))+'%'+"\n"+'獲勝次數'+str(count)+"\n"+'虧損次數:'+str(loss)+"\n"+'最大獲利率:'+str(round(max(win_con),2))+'%'+"\n"+'最大虧損率:'+str(round(min(los_con),2))+'%'
tk.messagebox.showinfo("績效",str_tmp)
def clock():
t=time.strftime('%I:%M:%S',time.localtime())
if t!='':
var5.set(date[int(var.get())])
var6.set(date[int(var2.get())])
root.after(500,clock)
def drawPic():
try:sampleCount=int(inputEntry.get())
except:
sampleCount=50
inputEntry.delete(0,END)
inputEntry.insert(0,'50')
drawPic.f.clf()
drawPic.a =drawPic.f.add_axes([0.1,0.4,0.8,0.5])
drawPic.a2 = drawPic.f.add_axes([0.1,0.190,0.8,0.2])
drawPic.f.subplots_adjust(hspace=0)
drawPic.f.tight_layout()
drawPic.a.xaxis_date()
drawPic.a2.xaxis_date()
for label in drawPic.a.xaxis.get_ticklabels():
label.set_rotation(45)
for label in drawPic.a2.xaxis.get_ticklabels():
label.set_rotation(45)
drawPic.a.set_title("K線圖", fontsize=20)
drawPic.a2.set_xlabel("時間", fontsize=10)
drawPic.a.set_ylabel("股價", fontsize=10)
drawPic.a2.set_ylabel("成交量", fontsize=10)
# 设置X轴刻度为日期时间
#data_list.reverse()
sma_5 = talib.SMA(np.array(close), 5)
sma_10 = talib.SMA(np.array(close), 10)
sma_20 = talib.SMA(np.array(close), 20)
#print (len(data_list))
start =int(var.get())
end=int(var2.get())
if(var4.get()==1):
drawPic.a.plot( date_ex[start:end:5],sma_5[start:end:5], label='SMA5')
drawPic.a.plot( date_ex[start:end:10],sma_10[start:end:10], label='SMA10')
drawPic.a.plot( date_ex[start:end:20],sma_20[start:end:20], label='SMA20')
drawPic.a.legend(loc='upper left')
var5.set(date[start])
var6.set(date[end])
candlestick_ohlc(drawPic.a, data_list[start:end], width=0.5, colorup='r', colordown='g')
print (vol)
volume_overlay3(drawPic.a2,data_list2[start:end], colorup='r', colordown='g', width=0.5, alpha=0.8)
if(var3.get()==1):
for x in range(0,len(buy_list),1):
drawPic.a.annotate('', xy=(buy_list[x][0],buy_list[x][1]), xytext=(-15, -27),
textcoords='offset points', ha="center",
arrowprops=dict(facecolor='black', color='green',width=0.5),
)
for x in range(0,len(sell_list),1):
drawPic.a.annotate('', xy=(sell_list[x][0],sell_list[x][1]), xytext=(-17, 20),
textcoords='offset points', ha="center",
arrowprops=dict(facecolor='black', color='red',width=0.5),
)
drawPic.a.grid()
drawPic.a2.grid()
drawPic.canvas.show()
root=tk.Tk()
tk.Button(root,text='回測',command=drawPic).grid(row=1,column=2,columnspan=3)
tk.Button(root,text='績效',command=show_info).grid(row=2,column=2,columnspan=3)
drawPic.f = Figure(figsize=(15,7))
drawPic.canvas = FigureCanvasTkAgg(drawPic.f, master=root)
drawPic.canvas.show()
drawPic.canvas.get_tk_widget().grid(row=0, columnspan=3)
_job = None
var = DoubleVar(root,0)
var2 = DoubleVar(root,0)
var3 = tk.IntVar(root,0)
var4 = tk.IntVar(root,0)
var5 = tk.StringVar(root,0)
var6 = tk.StringVar(root,0)
w=tk.Scale(root, from_=start, to=end-1, orient=HORIZONTAL, variable = var ).grid(row=2,column=0)
w2=tk.Scale(root, from_=start, to=end-1, orient=HORIZONTAL, variable = var2).grid(row=2,column=1)
c1 = tk.Checkbutton(root, text='買賣點', variable=var3, onvalue=1, offvalue=0,
).grid(row=3,column=2)
c2 = tk.Checkbutton(root, text='KD線', variable=var4, onvalue=1, offvalue=0,
).grid(row=4,column=2)
tk.Label(root,text='请输入样本数量:').grid(row=1,column=0)
inputEntry=tk.Entry(root)
inputEntry.grid(row=1,column=1)
inputEntry.insert(0,'50')
data_label = tk.Label(root, text='-----', textvariable=var5).grid(row=3,column=0)
data_label2 = tk.Label(root, text='-----', textvariable=var6).grid(row=3,column=1)
clock()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
root.mainloop()
view raw macd2.py hosted with ❤ by GitHub

原生成交量真的畫很醜我們來改造一下


原生,土砲一下

for x in data_list2[start:end]:
if((x[1]-x[4])<0):
pos_d.append(x[0])
pos_v.append(x[5])
elif ((x[1]-x[4])>0):
neg_d.append(x[0])
neg_v.append(x[5])
drawPic.a2.bar(pos_d,pos_v,color='green',width=1,align='center')
drawPic.a2.bar(neg_d,neg_v,color='red',width=1,align='center')
#drawPic.a2.bar(pos[0][0],pos[0][1],color='green',width=1,align='center')
#print (tupleto_listtmp)
# for x in pos:
# drawPic.a2.bar(x[0],x[1],color='green',width=1,align='center')
#for x in neg:
# drawPic.a2.bar(x[0],x[1],color='red',width=1,align='center')
#drawPic.a2.bar(pos[:][0],pos[:][1],color='green',width=1,align='center')
#drawPic.a2.bar(neg[:][0],neg[:][1],color='red',width=1,align='center')
#volume_overlay3(drawPic.a2,data_list2[start:end], colorup='r', colordown='g',
view raw volume.py hosted with ❤ by GitHub