代码拉取完成,页面将自动刷新
同步操作将从 张洋/backtrader 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
from PyQt6 import QtCore, QtWidgets, uic
import pandas as pd
import sys, os
from DataFile import DataFile
from dataManager import DataManager
from logger_module import logger
from cerebroConfig import CerebroConfig
from datetime import datetime, timedelta
from functools import lru_cache
import requests
@lru_cache()
def code_id_map_em() -> dict:
"""
东方财富-股票和市场代码
https://quote.eastmoney.com/center/gridlist.html#hs_a_board
:return: 股票和市场代码
:rtype: dict
"""
url = "https://80.push2.eastmoney.com/api/qt/clist/get"
params = {
"pn": "1",
"pz": "50000",
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"fid": "f3",
"fs": "m:1 t:2,m:1 t:23",
"fields": "f12",
"_": "1623833739532",
}
r = requests.get(url, timeout=15, params=params)
data_json = r.json()
if not data_json["data"]["diff"]:
return dict()
temp_df = pd.DataFrame(data_json["data"]["diff"])
temp_df["market_id"] = 1
temp_df.columns = ["sh_code", "sh_id"]
code_id_dict = dict(zip(temp_df["sh_code"], temp_df["sh_id"]))
params = {
"pn": "1",
"pz": "50000",
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"fid": "f3",
"fs": "m:0 t:6,m:0 t:80",
"fields": "f12",
"_": "1623833739532",
}
r = requests.get(url, timeout=15, params=params)
data_json = r.json()
if not data_json["data"]["diff"]:
return dict()
temp_df_sz = pd.DataFrame(data_json["data"]["diff"])
temp_df_sz["sz_id"] = 0
code_id_dict.update(dict(zip(temp_df_sz["f12"], temp_df_sz["sz_id"])))
params = {
"pn": "1",
"pz": "50000",
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"fid": "f3",
"fs": "m:0 t:81 s:2048",
"fields": "f12",
"_": "1623833739532",
}
r = requests.get(url, timeout=15, params=params)
data_json = r.json()
if not data_json["data"]["diff"]:
return dict()
temp_df_sz = pd.DataFrame(data_json["data"]["diff"])
temp_df_sz["bj_id"] = 0
code_id_dict.update(dict(zip(temp_df_sz["f12"], temp_df_sz["bj_id"])))
return code_id_dict
def stock_zh_a_hist(
symbol: str = "000001",
period: str = "daily",
start_date: str = "19700101",
end_date: str = "20500101",
adjust: str = "",
timeout: float = None,
) -> pd.DataFrame:
"""
东方财富网-行情首页-沪深京 A 股-每日行情
https://quote.eastmoney.com/concept/sh603777.html?from=classic
:param symbol: 股票代码
:type symbol: str
:param period: choice of {'daily', 'weekly', 'monthly'}
:type period: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:param adjust: choice of {"qfq": "前复权", "hfq": "后复权", "": "不复权"}
:type adjust: str
:param timeout: choice of None or a positive float number
:type timeout: float
:return: 每日行情
:rtype: pandas.DataFrame
"""
code_id_dict = code_id_map_em()
adjust_dict = {"qfq": "1", "hfq": "2", "": "0"}
period_dict = {"daily": "101", "weekly": "102", "monthly": "103"}
url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f116",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period_dict[period],
"fqt": adjust_dict[adjust],
"secid": f"{code_id_dict[symbol]}.{symbol}",
"beg": start_date,
"end": end_date,
"_": "1623766962675",
}
r = requests.get(url, params=params, timeout=timeout)
data_json = r.json()
if not (data_json["data"] and data_json["data"]["klines"]):
return pd.DataFrame()
temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
temp_df["股票代码"] = symbol
temp_df.columns = [
"日期",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
"股票代码",
]
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"], errors="coerce")
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"], errors="coerce")
temp_df["最高"] = pd.to_numeric(temp_df["最高"], errors="coerce")
temp_df["最低"] = pd.to_numeric(temp_df["最低"], errors="coerce")
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"], errors="coerce")
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"], errors="coerce")
temp_df["振幅"] = pd.to_numeric(temp_df["振幅"], errors="coerce")
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
temp_df = temp_df[
[
"日期",
"股票代码",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
]
return temp_df
class CreateCerebroUI(QtWidgets.QWidget):
def __init__(self, controller, parent = None):
super(CreateCerebroUI, self).__init__()
self.controller = controller
self.parent = parent
#self.setParent(parent)
# It does not finish by a "/"
self.cerebro_directory = './user_cerebro/'
self.current_dir_path = os.path.dirname(os.path.realpath(__file__))
uic.loadUi( self.current_dir_path + "/ui/createCerebro.ui", self)
self.autoRB = self.findChild(QtWidgets.QRadioButton, "autoRB")
self.manualRB = self.findChild(QtWidgets.QRadioButton, "manualRB")
self.cerebroNameLE = self.findChild(QtWidgets.QLineEdit, "cerebroNameLE")
self.createCerebroPB = self.findChild(QtWidgets.QToolButton, "createCerebroPB")
self.createErrorLabel = self.findChild(QtWidgets.QLabel, "createErrorLabel")
self.tabRB = self.findChild(QtWidgets.QRadioButton, "tabRB")
self.commaRB = self.findChild(QtWidgets.QRadioButton, "commaRB")
self.semicolonRB = self.findChild(QtWidgets.QRadioButton, "semicolonRB")
self.openFilePB = self.findChild(QtWidgets.QToolButton, "openFilePB")
self.downloadPB = self.findChild(QtWidgets.QToolButton, "downloadPB")
self.loadFilePB = self.findChild(QtWidgets.QPushButton, "loadFilePB")
self.filePathLE = self.findChild(QtWidgets.QLineEdit, "filePathLE")
self.loadPathLE = self.findChild(QtWidgets.QLineEdit, "loadPathLE")
self.dateEdit = self.findChild(QtWidgets.QDateEdit, "dateEdit")
self.errorLabel = self.findChild(QtWidgets.QLabel, "errorLabel")
# Connect slots : open file
self.createCerebroPB.clicked.connect( self.createCerebro )
self.openFilePB.clicked.connect( self.openFileDialog )
self.downloadPB.clicked.connect( self.downloadDataFile )
self.loadFilePB.clicked.connect( self.createDataFile )
self.dataManager = DataManager()
self.cerebroConfig = None
pass
def createCerebro(self):
cerebroType = 'Auto' if self.autoRB.isChecked() else 'Manual'
cerebroName = self.cerebroNameLE.text().strip()
directory = self.cerebro_directory + cerebroName
if not os.path.exists(directory):
os.makedirs(directory)
else:
self.createErrorLabel.setStyleSheet("color:red")
self.createErrorLabel.setText("回测已存在,请换一个名字!!!")
return
self.cerebroConfig = CerebroConfig(cerebroName)
csvConfig = {}
self.cerebroConfig.saveParameter("name", cerebroName)
self.cerebroConfig.saveParameter("type", cerebroType)
self.cerebroConfig.saveParameter("csvConfig", csvConfig)
self.createErrorLabel.setStyleSheet("color:green")
self.createErrorLabel.setText("创建成功!")
pass
def openFileDialog(self):
self.dataFilePath = QtWidgets.QFileDialog.getOpenFileName(self, 'Open data file', self.current_dir_path + "/data","CSV files (*.csv)")[0]
self.filePathLE.setText(self.dataFilePath)
self.setDateTime()
pass
def downloadDataFile(self):
fileName = self.loadPathLE.text()
self.dataFilePath = self.current_dir_path + "/data/" + fileName + ".csv"
self.filePathLE.setText(self.dataFilePath)
try:
self.errorLabel.setStyleSheet("color:green")
self.errorLabel.setText("正在下载。。。。。")
dongfang_df = stock_zh_a_hist(symbol=fileName).iloc[:, :7]
dongfang_df.drop(columns=['股票代码'], inplace=True)
new_column_order = ['日期', '开盘', '最高','最低','收盘','成交量']
dongfang_df.to_csv(self.dataFilePath, sep=",", index=False, header=False, columns=new_column_order)
self.errorLabel.setText("下载完成,请点击载入数据。")
self.setDateTime()
except:
logger.error("下载失败:" + str(sys.exc_info()[0]))
self.errorLabel.setStyleSheet("color:red")
self.errorLabel.setText("下载失败:" + str(sys.exc_info()[0]))
pass
def createDataFile(self):
dayTimeFormat1 = "yyyy-MM-dd"
dayTimeFormat2 = "%Y-%m-%d"
csvConfig = {}
csvConfig['fileName'] = os.path.basename(self.dataFilePath)
csvConfig['filePath'] = self.dataFilePath
csvConfig['separator'] = ',' if self.commaRB.isChecked() else '\t' if self.tabRB.isChecked() else ';'
csvConfig['timeFormat'] = self.dataManager.DatetimeFormat(self.dataFilePath)
csvConfig['index'] = 0
start_str = self.dateEdit.date().toString(dayTimeFormat1)
start_obj = datetime.strptime(start_str,dayTimeFormat2)
csvConfig['start_date'] = start_obj.strftime(csvConfig['timeFormat'])
logger.info(csvConfig['start_date'])
if self.cerebroConfig == None:
self.errorLabel.setStyleSheet("color:red")
self.errorLabel.setText("导入文件失败,未创建回测实例!!!")
return
else:
self.errorLabel.setText("")
self.cerebroConfig.saveParameter("csvConfig", csvConfig)
#self.controller.cerebroConfig = self.cerebroConfig
if self.controller.loadCerebroConfig(self.cerebroNameLE.text().strip()):
self.errorLabel.setText("")
self.createErrorLabel.setText("")
self.hide()
else:
self.errorLabel.setText("导入文件失败,选择格式不对!!!")
def setDateTime(self):
timeFormat = self.dataManager.DatetimeFormat(self.dataFilePath)
date_str = self.dataManager.GetfirstDatetimeStr(self.dataFilePath)
date_obj = datetime.strptime(date_str, timeFormat)
next_day = date_obj + timedelta(days=1)
self.dateEdit.setMinimumDate(next_day)
self.dateEdit.setDate(next_day)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。