Skip to content

Commit

Permalink
[feat] add load market data
Browse files Browse the repository at this point in the history
  • Loading branch information
Charmve committed Aug 9, 2024
1 parent 42ff5bb commit 94c7075
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 13 deletions.
2 changes: 1 addition & 1 deletion qbot/common/file_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import re

import os

def extract_content(text):
pattern = r"\((.*?)\)" # 匹配()之间的内容
Expand Down
16 changes: 16 additions & 0 deletions utils/common/utils.py → qbot/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,19 @@ def cri(self, message):


log = logger("log.txt")


import socket
def check_port_in_use(port, host='127.0.0.1'):
s = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
s.connect((host, int(port)))
return True
except socket.error:
return False
finally:
if s:
s.close()

24 changes: 24 additions & 0 deletions qbot/gui/global_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from qbot.common.logging.logger import LOGGER as logger


class GlobalEvent:
MSG_TYPE_SERIES = 1

def __init__(self):
self.observers = {}

def add_observer(self, msg_type, observer):
if msg_type in self.observers.keys():
self.observers[msg_type].append(observer)
else:
self.observers[msg_type] = [observer]

def notify(self, msg_type, data):
logger.info("[GlobalEvent] get a notify ...")
# print("data: ", data)
if msg_type in self.observers.keys():
for observer in self.observers[msg_type]:
observer.handle_data(data)


GlobalEvent = GlobalEvent()
21 changes: 21 additions & 0 deletions qbot/gui/gui_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import wx


def _pydate2wxdate(date):
import datetime

assert isinstance(date, (datetime.datetime, datetime.date))
tt = date.timetuple()
dmy = (tt[2], tt[1] - 1, tt[0])
return wx.DateTimeFromDMY(*dmy)


def _wxdate2pydate(date):
import datetime

assert isinstance(date, wx.DateTime)
if date.IsValid():
ymd = map(int, date.FormatISODate().split("-"))
return datetime.date(*ymd)
else:
return None
277 changes: 275 additions & 2 deletions qbot/gui/panels/panel_backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"""
import wx

from qbot.gui import gui_utils
from qbot.gui.config import DATA_DIR_BKT_RESULT
from qbot.gui.widgets.widget_web import WebPanel
from qbot.common.file_utils import extract_content
Expand Down Expand Up @@ -122,18 +123,223 @@ def _init_para_notebook(self):
self.ParaPaPanel = wx.Panel(self.ParaNoteb, -1) # 形态选股 patten

# 第二层布局
# self.ParaStPanel.SetSizer(self.add_stock_para_lay(self.ParaStPanel))
self.ParaStPanel.SetSizer(self.add_stock_para_lay(self.ParaStPanel))
self.ParaBtPanel.SetSizer(self.add_backt_para_lay(self.ParaBtPanel))
# self.ParaPtPanel.SetSizer(self.add_pick_para_lay(self.ParaPtPanel))
# self.ParaPaPanel.SetSizer(self.add_patten_para_lay(self.ParaPaPanel))

# self.ParaNoteb.AddPage(self.ParaStPanel, "行情参数")
self.ParaNoteb.AddPage(self.ParaStPanel, "行情参数")
self.ParaNoteb.AddPage(self.ParaBtPanel, "回测参数")
# self.ParaNoteb.AddPage(self.ParaPtPanel, "条件选股")
# self.ParaNoteb.AddPage(self.ParaPaPanel, "形态选股")

return self.ParaNoteb

def add_stock_para_lay(self, sub_panel):

# 行情参数
stock_para_sizer = wx.BoxSizer(wx.HORIZONTAL)

# 行情参数——日历控件时间周期
self.dpc_end_time = wx.adv.DatePickerCtrl(
sub_panel,
-1,
style=wx.adv.DP_DROPDOWN | wx.adv.DP_SHOWCENTURY | wx.adv.DP_ALLOWNONE,
) # 结束时间
self.dpc_start_time = wx.adv.DatePickerCtrl(
sub_panel,
-1,
style=wx.adv.DP_DROPDOWN | wx.adv.DP_SHOWCENTURY | wx.adv.DP_ALLOWNONE,
) # 起始时间

self.start_date_box = wx.StaticBox(sub_panel, -1, "开始日期(Start)")
self.end_date_box = wx.StaticBox(sub_panel, -1, "结束日期(End)")
self.start_date_sizer = wx.StaticBoxSizer(self.start_date_box, wx.VERTICAL)
self.end_date_sizer = wx.StaticBoxSizer(self.end_date_box, wx.VERTICAL)
self.start_date_sizer.Add(
self.dpc_start_time,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=2,
)
self.end_date_sizer.Add(
self.dpc_end_time,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=2,
)

date_time_now = wx.DateTime.Now() # wx.DateTime格式"03/03/18 00:00:00"
self.dpc_end_time.SetValue(date_time_now)
self.dpc_start_time.SetValue(date_time_now.SetYear(date_time_now.year - 1))

self.Bind(wx.adv.EVT_DATE_CHANGED, self._on_end_time_changed, self.dpc_end_time)
self.Bind(
wx.adv.EVT_DATE_CHANGED, self._on_start_time_changed, self.dpc_start_time
)

self.backtest_opts["end_time"] = gui_utils._wxdate2pydate(
self.dpc_end_time.GetValue()
).strftime("%Y%m%d")
self.backtest_opts["start_time"] = gui_utils._wxdate2pydate(
self.dpc_start_time.GetValue()
).strftime("%Y%m%d")

# 行情参数——输入股票代码
self.stock_code_box = wx.StaticBox(
sub_panel, -1, "交易标的(股票/期货/比特币)代码"
)
self.stock_code_sizer = wx.StaticBoxSizer(self.stock_code_box, wx.VERTICAL)
self.stock_code_input = wx.TextCtrl(
sub_panel, -1, "399006.SZ", style=wx.TE_PROCESS_ENTER
)
self.stock_code_sizer.Add(
self.stock_code_input,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=2,
)
self.stock_code_input.Bind(wx.EVT_TEXT_ENTER, self._ev_enter_stcode)
self.Bind(wx.EVT_TEXT, self._on_combobox_code_changed, self.stock_code_input)
select_code = self.stock_code_input.GetValue()
logger.debug(f"select_code: {select_code}")
self.backtest_opts["code"] = select_code

# 行情参数——股票周期选择
self.stock_period_box = wx.StaticBox(sub_panel, -1, "股票周期")
self.stock_period_sizer = wx.StaticBoxSizer(self.stock_period_box, wx.VERTICAL)
self.stock_period_cbox = wx.ComboBox(
sub_panel, -1, "", choices=["30分钟", "60分钟", "日线", "周线"]
)
self.stock_period_cbox.SetSelection(2)
self.stock_period_sizer.Add(
self.stock_period_cbox,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=2,
)

# 行情参数——股票复权选择
self.stock_authority_box = wx.StaticBox(sub_panel, -1, "股票复权")
self.stock_authority_sizer = wx.StaticBoxSizer(
self.stock_authority_box, wx.VERTICAL
)
self.stock_authority_cbox = wx.ComboBox(
sub_panel, -1, "", choices=["前复权", "后复权", "不复权"]
)
self.stock_authority_cbox.SetSelection(2)
self.stock_authority_sizer.Add(
self.stock_authority_cbox,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=2,
)

# 行情参数——多子图显示
self.pick_graph_box = wx.StaticBox(sub_panel, -1, "多子图显示")
self.pick_graph_sizer = wx.StaticBoxSizer(self.pick_graph_box, wx.VERTICAL)
self.pick_graph_cbox = wx.ComboBox(
sub_panel,
-1,
"未开启",
choices=[
"未开启",
"A股票走势-MPL",
"B股票走势-MPL",
"C股票走势-MPL",
"D股票走势-MPL",
"A股票走势-WEB",
"B股票走势-WEB",
"C股票走势-WEB",
"D股票走势-WEB",
],
style=wx.CB_READONLY | wx.CB_DROPDOWN,
)
self.pick_graph_cbox.SetSelection(0)
self.pick_graph_last = self.pick_graph_cbox.GetSelection()
self.pick_graph_sizer.Add(
self.pick_graph_cbox,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=2,
)
# self.pick_graph_cbox.Bind(wx.EVT_COMBOBOX, self._ev_select_graph)

# 行情参数——股票组合分析
self.group_analy_box = wx.StaticBox(sub_panel, -1, "投资组合分析")
self.group_analy_sizer = wx.StaticBoxSizer(self.group_analy_box, wx.VERTICAL)
self.group_analy_cmbo = wx.ComboBox(
sub_panel,
-1,
"预留A",
choices=["预留A", "收益率/波动率", "走势叠加分析", "财务指标评分-预留"],
style=wx.CB_READONLY | wx.CB_DROPDOWN,
) # 策略名称
self.group_analy_sizer.Add(
self.group_analy_cmbo,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=2,
)
# self.group_analy_cmbo.Bind(wx.EVT_COMBOBOX, self._ev_group_analy) # 绑定ComboBox事件

# 回测按钮
self.load_data_but = wx.Button(sub_panel, -1, "加载数据")
self.load_data_but.SetBackgroundColour(wx.Colour(76, 187, 23)) # 设置背景颜色
# self.load_data_but.Bind(wx.EVT_BUTTON, self._ev_start_run) # 绑定按钮事件
self.load_data_but.Bind(wx.EVT_BUTTON, self.LoadData) # 绑定按钮事件

stock_para_sizer.Add(
self.start_date_sizer,
proportion=0,
flag=wx.EXPAND | wx.CENTER | wx.ALL,
border=5,
)
stock_para_sizer.Add(
self.end_date_sizer,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=5,
)
stock_para_sizer.Add(
self.stock_code_sizer,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=5,
)
stock_para_sizer.Add(
self.stock_period_sizer,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=5,
)
stock_para_sizer.Add(
self.stock_authority_sizer,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=5,
)
stock_para_sizer.Add(
self.pick_graph_sizer,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=5,
)
stock_para_sizer.Add(
self.group_analy_sizer,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=5,
)
stock_para_sizer.Add(
self.load_data_but,
proportion=0,
flag=wx.EXPAND | wx.ALL | wx.CENTER,
border=5,
)

return stock_para_sizer

def add_backt_para_lay(self, sub_panel):

# 回测参数
Expand Down Expand Up @@ -327,9 +533,76 @@ def add_backt_para_lay(self, sub_panel):

return back_para_sizer

def _ev_enter_stcode(self, event): # 输入股票代码

# 第一步:收集控件中设置的选项
st_code = self.stock_code_input.GetValue()
st_name = self.code_table.get_name(st_code)
self.backtest_opts["code"] = st_code
logger.info(f"回测股票/基金: You select {st_code}")

def _on_start_time_changed(self, event):
start_time = gui_utils._wxdate2pydate(self.dpc_start_time.GetValue()).strftime(
"%Y%m%d"
)
self.backtest_opts["start_time"] = start_time
logger.info(f"start_time: {start_time}")

def _on_end_time_changed(self, event):
end_time = gui_utils._wxdate2pydate(self.dpc_end_time.GetValue()).strftime(
"%Y%m%d"
)
self.backtest_opts["end_time"] = end_time
logger.info(f"end_time: {end_time}")

def _on_init_cash_changed(self, event):
self.backtest_config["init_cash"] = self.init_cash_input.GetValue()

def _on_slippage_changed(self, event):
self.backtest_config["slippage"] = self.init_slippage_input.GetValue()

def _on_stake_changed(self, event):
self.backtest_config["stake"] = self.init_stake_input.GetValue()

def _on_commission_changed(self, event):
self.backtest_config["commission"] = self.init_commission_input.GetValue()

def _on_stamp_duty_changed(self, event):
self.backtest_config["stamp_duty"] = self.init_tax_input.GetValue()

# def _on_text_changed(self, event):
# with open(RESULT_DIR.joinpath("backtest.log"), "r") as f:
# self.log_text_ctrl.SetValue(f.read())

def _on_combobox_benchmarks_changed(self, event):
self.select_benchmark = self.stock_benchmark_cbox.GetValue()
self.benchmark_code = extract_content(self.select_benchmark)[0]
logger.debug(f"select_benchmark: {self.benchmark_code}")
self.backtest_opts["benchmark"] = self.benchmark_code
logger.info(f"基准: You select {self.benchmark_code}")

# data_files_tmp = [x for x in self.data_files if x != self.benchmark_code]
# # logger.debug(f"new code list: {data_files_tmp}")
# self.combo_codes.SetItems(data_files_tmp)
# self.combo_codes.SetValue("399006.SZ")

def _on_combobox_strategy_changed(self, event):
select_strategy = self.stock_strategy_cbox.GetValue()
self.backtest_opts["select_strategy"] = select_strategy
logger.info(f"交易策略: You select {select_strategy}")

def _on_combobox_code_changed(self, event):
select_code = self.stock_code_input.GetValue()
self.backtest_opts["code"] = select_code
logger.info(f"回测股票/基金: You select {select_code}")

def _ev_trade_log(self, event):
pass

def StartBacktest(self, event):
print("在线回测属于付费功能,请联系微信:Yida_Zhang2")
pass

def LoadData(self, event):
print("请联系微信:Yida_Zhang2 开通功能")
pass
Loading

0 comments on commit 94c7075

Please sign in to comment.