巴菲特模拟器。给你初始资金100W,拉取实际的A股股市信息,在虚拟盘中进行操作,没有T+1的限制,试试自己到底是股神还是韭菜。
一 金融数据库tushare准备
这边使用了免费量化数据库tushare,简单的注册登录即可以免费获取到一些基本的量化数据。链接如下:tushare量化库。想做的这个小工具比较简单,使用一些最基础的量化数据即可,比如股票现价,交易日历等。
注册成功之后会有一组码,在程序中执行ts.set_token()调用即可使用该库。程序中的使用如下:
import tushare as ts #量化分析数据库
import pandas as pd #数据解析处理
from gui_simtrade import TKDemo
def main(): #主函数
ts.set_token('30f5d834d4b8dc18d4e8d546b645dd38af83072cc3908606cc503a7d')
pro = ts.pro_api() # 初始化pro接口
TKDemo()
if __name__=="__main__":
main()
至于其具体函数的调用,可以参考下面的代码(调用股票日历trade_cal,查看其返回的参数is_open,进而判断当前操作的系统时间是不是股票交易时间):
def isTradeTime(self): # 判断是否是交易时间
date_now = datetime.datetime.now().strftime('%Y%m%d')
open_list = ts.pro_api().trade_cal(**{
"exchange": "",
"cal_date": date_now,
"start_date": "",
"end_date": "",
"is_open": "",
"limit": "",
"offset": ""
}, fields=[
"is_open"
])
is_tarde_day = open_list.to_dict()['is_open'].values()
if is_tarde_day:
time_now = datetime.datetime.now().strftime('%H%M%S')
if 93000 < int(time_now) < 110000 or 130000 < int(time_now) < 150000:
return 1
else:
return 0
else:
return 0
二 tkinter界面的实现
这边因为涉及到一些交易操作,所以一个GUI就必不可少,我用到了tkinter图形库来实现这个界面。界面中的控件初始化如下:
class TKDemo:
def __init__(self):
self.gui = tkinter.Tk()
self.gui.title('模拟交易软件')
self.gui.geometry('1000x500')
frame1 = tkinter.LabelFrame(self.gui, text="市场情况", width=500, height=500)
frame1.place(x=0, y=0)
frame2 = tkinter.LabelFrame(self.gui, text="我的交易", width=500, height=500)
frame2.place(x=500, y=0)
# 市场情况框架中的控件
l1 = tkinter.Label(frame1, text='搜索股票代码')
l1.place(x=60, y=10)
self.code = tkinter.StringVar()
e1= tkinter.Entry(frame1, textvariable=self.code)
e1.place(x=150, y=10)
b_add = tkinter.Button(frame1,
text='添加',
command=self.execOpAdd)
b_add.place(x=310, y=10)
b_del = tkinter.Button(frame1,
text='删除',
command=self.execOpDel)
b_del.place(x=350, y=10)
self.tree1 = ttk.Treeview(frame1, height=18, show="headings", columns=columns1)
self.tree1.column("代码", width=100, anchor='center') # 表示列,不显示
self.tree1.column("名称", width=200, anchor='center')
self.tree1.column("现价", width=200, anchor='center')
self.tree1.heading("代码", text="代码") # 显示表头
self.tree1.heading("名称", text="名称")
self.tree1.heading("现价", text="现价")
self.tree1.bind('<Double-1>', self.treeviewClick1)
self.tree1.place(x=0, y=250)
e1.bind("<Return>", self.execOpAdd_bind) # 搜索框绑定回车键,直接添加
e1.bind("<Delete>", self.execOpDel_bind) # 搜索框绑定DEL键,直接删除
# 我的交易框架中的控件
l2_t = tkinter.Label(frame2, text='总资产')
l2_t.place(x=0, y=3)
self.s2 = tkinter.StringVar()
self.s2.set(str(TOTAL_ASSETS))
l2 = tkinter.Label(frame2, textvariable=self.s2, width=10, height=1, bg='white', fg='red', anchor='w', font=("Courier", 11, "italic"))
l2.place(x=50,y=0)
l3_t = tkinter.Label(frame2, text='总盈亏')
l3_t.place(x=160, y=3)
self.s3 = tkinter.StringVar()
l3 = tkinter.Label(frame2, textvariable=self.s3, width=10, height=1, bg='white', fg='red', anchor='w', font=("Courier", 11, "italic"))
l3.place(x=220, y=0)
l4_t = tkinter.Label(frame2, text='剩余可用')
l4_t.place(x=330, y=3)
self.s4 = tkinter.StringVar()
l4 = tkinter.Label(frame2, textvariable=self.s4, width=10, height=1, bg='white', fg='red', anchor='w', font=("Courier", 11, "italic"))
l4.place(x=390, y=0)
l5_t = tkinter.Label(frame2, text='总市值')
l5_t.place(x=0, y=53)
self.s5 = tkinter.StringVar()
l5 = tkinter.Label(frame2, textvariable=self.s5, width=10, height=1, bg='white', fg='red', anchor='w', font=("Courier", 11, "italic"))
l5.place(x=50, y=50)
l6_t = tkinter.Label(frame2, text='持仓盈亏')
l6_t.place(x=160, y=53)
self.s6 = tkinter.StringVar()
l6 = tkinter.Label(frame2, textvariable=self.s6, width=10, height=1, bg='white', fg='red', anchor='w', font=("Courier", 11, "italic"))
l6.place(x=220, y=50)
l7_t = tkinter.Label(frame2, text='综合评价')
l7_t.place(x=330, y=53)
self.s7 = tkinter.StringVar()
l7 = tkinter.Label(frame2, textvariable=self.s7, width=10, height=1, bg='white', fg='red', anchor='w', font=("Courier", 11, "italic"))
l7.place(x=390, y=50)
self.tree2 = ttk.Treeview(frame2, height=18, show="headings", columns=columns2)
self.tree2.column("代码", width=100, anchor='center') # 表示列,不显示
self.tree2.column("名称", width=100, anchor='center')
self.tree2.column("现价", width=100, anchor='center')
self.tree2.column("持仓", width=200, anchor='center')
self.tree2.heading("代码", text="代码") # 显示表头
self.tree2.heading("名称", text="名称")
self.tree2.heading("现价", text="现价")
self.tree2.heading("持仓", text="持仓")
self.tree2.bind('<Double-1>', self.treeviewClick2)
self.tree2.place(x=0, y=250)
# 我的持仓初始化
global mylist
mylist = self.initMyList()
global data_all
# 获得所有的个股信息列表,用来比对输入的代码有效性
data_all = ts.pro_api().stock_basic(**{
"ts_code": "",
"name": "",
"exchange": "",
"market": "",
"is_hs": "",
"list_status": "",
"limit": "",
"offset": ""
}, fields=[
"ts_code"
])
self.getCurPrice() # 循环获得现价
self.gui.mainloop()
其中,一些具体按钮的操作这边不做一一列举,参考附件中给出来的开源代码。
三 文件操作
模拟的持仓信息不能在关闭程序的时候就消失掉,所以需要将持仓信息保存在本地的文件中,这边调用了json库,将内容保存为本地的json文件以供随时访问。
例如下面的持仓初始化,就是在每次打开该软件的时候,从本地json文件中读出保存的持仓信息:
def initMyList(self): # 我的持仓初始化
global remain
tmp = open(PATH_BAK, 'a')
tmp.close()
with open(PATH_BAK, 'r') as f: # 打开文件
filetmp = f.read()
if filetmp:
fileread = json.loads(filetmp) # 读记录
print('读取保存的用户信息{}'.format(fileread))
remain = fileread.pop('remain')
return fileread
else:
fileread = {}
return fileread
综上,即可实现该模拟交易的小工具,交易界面如下:
四 附录:
【1】开源库地址:Python_SimTrade: 模拟交易小软件,量化交易
【2】量化交易数据库地址:Tushare大数据社区