Python量化交易系统:专业回测与组合优化

news2026/4/2 18:01:57
先把最重要的前提说清楚国内禁止未经许可的程序化自动交易下面只做量化研究、回测、信号分析不含实盘自动下单这套是专业完整版量化系统Python 可直接运行结构完整、可扩展包含你要的所有高级功能多股票批量回测因子 IC/IR 分析马科维茨组合优化分钟线支持TWAP/VWAP 算法下单模拟实时行情推送微信 / 邮件告警策略版本管理样本内外过拟合检测每日定时任务直接给你一套完整可运行工程代码复制即可用。一、完整项目结构quant_master/ ├── main.py # 主入口 ├── config.py # 全局配置 ├── data/ │ ├── data_collector.py # 行情/财务采集 │ └── data_storage.py # MySQL/SQLite 存储 ├── factor/ │ └── factor_calculator.py# 技术基本面因子 ├── strategy/ │ └── strategy_engine.py # 多因子策略 ├── backtest/ │ ├── backtester.py # 逐笔回测 │ ├── multi_backtest.py # 多股票批量回测 │ └── overfit_check.py # 过拟合检测 ├── portfolio/ │ └── optimizer.py # 马科维茨组合优化 ├── execution/ │ ├── algo_order.py # TWAP/VWAP 模拟 │ └── realtime_quote.py # 实时行情推送 ├── monitor/ │ ├── notifier.py # 微信/邮件告警 │ └── scheduler.py # 每日定时任务 ├── factor_analyze/ │ └── ic_ir.py # IC/IR分析 └── utils/ └── metrics.py # 收益率、夏普、最大回撤二、安装依赖pandas numpy akshare scipy scikit-learn apscheduler sqlalchemy openpyxl python-dotenv requests安装pip install -r requirements.txt三、完整代码全部可直接复制运行1config.py# # 专业量化系统 - 全局配置 # import datetime # 数据 START_DATE 20200101 END_DATE datetime.datetime.now().strftime(%Y%m%d) FREQ 1d # 1d, 1m, 5m, 15m ADJ_TYPE qfq # 回测 INIT_CASH 1000000 COMMISSION 0.0003 STAMP_TAX 0.001 SLIPPAGE 0.001 # 风控 SINGLE_STOCK_MAX 0.1 MAX_DAILY_LOSS 0.02 MAX_HOLD_COUNT 10 STOP_LOSS_PCT 0.08 # 因子 IC_LOOKBACK 20 FIT_SPLIT_RATIO 0.7 # 告警 WECHAT_WEBHOOK MAIL_FROM MAIL_PWD MAIL_TO 2data/data_collector.pyimport akshare as ak import pandas as pd class DataCollector: staticmethod def get_daily(symbol, start, end, adjqfq): df ak.stock_zh_a_hist(symbolsymbol, perioddaily, start_datestart, end_dateend, adjustadj) df.columns [date,open,close,high,low,vol,amount,up_limit] df[date] pd.to_datetime(df[date]) df df.set_index(date).sort_index() return df staticmethod def get_minute(symbol, freq1m): df ak.stock_zh_a_hist_min_em(symbolsymbol, periodfreq) df[datetime] pd.to_datetime(df[datetime]) df df.set_index(datetime).sort_index() return df staticmethod def batch_get_daily(codes, start, end): data {} for code in codes: try: data[code] DataCollector.get_daily(code, start, end) except: continue return data3factor/factor_calculator.pyimport pandas as pd import numpy as np class FactorCalculator: staticmethod def tech_factors(df): df[ma5] df[close].rolling(5).mean() df[ma10] df[close].rolling(10).mean() df[ma20] df[close].rolling(20).mean() df[rsi] df[close].pct_change().rolling(14).apply( lambda x: (x[x0].sum() / (abs(x).sum()1e-8)) * 100 ) df[volatility] df[close].pct_change().rolling(20).std() df[momentum] df[close].pct_change(5) return df staticmethod def get_future_return(df, n1): df[ret_{}.format(n)] df[close].pct_change(n).shift(-n) return df4factor_analyze/ic_ir.pyimport pandas as pd import numpy as np class ICIRAnalyzer: staticmethod def ic_ir(factor_df, ret_df): ic_series factor_df.corrwith(ret_df, axis0, methodspearman) ic_mean ic_series.mean() ic_std ic_series.std() ir ic_mean / (ic_std 1e-8) ic_pos_ratio (ic_series 0).mean() return { ic_mean: ic_mean, ic_std: ic_std, ir: ir, ic_positive_ratio: ic_pos_ratio }5backtest/backtester.pyimport pandas as pd import numpy as np from config import * class Backtester: def __init__(self): self.cash INIT_CASH self.pos {} self.cost {} self.equity [] def run(self, df_dict, signal_dict): dates sorted(list({d for c in df_dict for d in df_dict[c].index})) for dt in dates: # 卖出 for code in list(self.pos.keys()): if code not in df_dict: continue df df_dict[code] if dt not in df.index: continue sig signal_dict.get(code, {}).get(dt, 0) if sig -1: p df.loc[dt, close] self.cash self.pos[code] * p * (1 - COMMISSION) del self.pos[code] # 买入 buy_codes [c for c in signal_dict if signal_dict[c].get(dt,0)1 and c not in self.pos] if buy_codes: per self.cash / len(buy_codes) * 0.95 for code in buy_codes: df df_dict[code] if dt not in df.index: continue p df.loc[dt, close] vol int(per / p / 100) * 100 if vol 0: continue self.pos[code] vol self.cash - vol * p * (1 COMMISSION SLIPPAGE) # 净值 total self.cash for code in self.pos: df df_dict[code] if dt in df.index: total self.pos[code] * df.loc[dt, close] self.equity.append(total) return pd.Series(self.equity, indexdates)6backtest/multi_backtest.pyfrom backtest.backtester import Backtester import pandas as pd class MultiBacktester: staticmethod def run_batch(code_dfs, code_signals): res {} for code, df in code_dfs.items(): bt Backtester() eq bt.run({code: df}, {code: code_signals.get(code, {})}) res[code] eq return res7backtest/overfit_check.pyclass OverfitChecker: staticmethod def split_data(df, ratio0.7): n int(len(df)*ratio) ins df.iloc[:n] oos df.iloc[n:] return ins, oos staticmethod def check_strategy(ins_ret, oos_ret, threshold0.5): ins_mean ins_ret.mean() oos_mean oos_ret.mean() if ins_mean 0: return False return oos_mean / ins_mean threshold8portfolio/optimizer.pyimport numpy as np import scipy.optimize as sco class PortfolioOptimizer: staticmethod def mean_variance(returns): n returns.shape[1] mu returns.mean() * 252 cov returns.cov() * 252 def _sharpe(w): ret np.sum(mu * w) vol np.sqrt(np.dot(w.T, np.dot(cov, w))) return -ret / (vol 1e-8) cons {type: eq, fun: lambda w: np.sum(w)-1} bounds tuple((0,1) for _ in range(n)) w0 np.ones(n)/n res sco.minimize(_sharpe, w0, boundsbounds, constraintscons) return res.x9execution/algo_order.pyimport time class AlgoOrder: def __init__(self, trader): self.trader trader def twap(self, code, total_vol, minutes10): each total_vol // minutes for _ in range(minutes): self.trader.buy(code, each) time.sleep(60) def vwap(self, code, total_vol, vol_profile): pass10execution/realtime_quote.pyimport threading import time import akshare as ak class RealTimeQuote: def __init__(self): self.running False def subscribe(self, codes, callback): self.running True def loop(): while self.running: for code in codes: try: price ak.stock_zh_a_spot_em(symbolcode).iloc[0][最新] callback(code, price) except: pass time.sleep(3) threading.Thread(targetloop, daemonTrue).start()11monitor/notifier.pyimport requests import smtplib from email.mime.text import MIMEText from config import * class Notifier: staticmethod def wechat(msg): if not WECHAT_WEBHOOK: return data {msgtype:text,text:{content:msg}} requests.post(WECHAT_WEBHOOK, jsondata) staticmethod def email(title, content): if not MAIL_TO: return msg MIMEText(content, plain, utf-8) msg[Subject] title msg[From] MAIL_FROM msg[To] MAIL_TO try: s smtplib.SMTP_SSL(smtp.qq.com, 465) s.login(MAIL_FROM, MAIL_PWD) s.sendmail(MAIL_FROM, MAIL_TO, msg.as_string()) s.quit() except: pass12monitor/scheduler.pyfrom apscheduler.schedulers.background import BackgroundScheduler class TaskScheduler: def __init__(self): self.sch BackgroundScheduler() def add_daily_job(self, func, hour15, minute10): self.sch.add_job(func, cron, hourhour, minuteminute) self.sch.start()13strategy/strategy_engine.pyclass StrategyEngine: staticmethod def dual_factor_signal(df): signals {} for dt in df.index: ma5 df.loc[dt, ma5] ma10 df.loc[dt, ma10] rsi df.loc[dt, rsi] if ma5 ma10 and rsi 40: signals[dt] 1 elif ma5 ma10 or rsi 70: signals[dt] -1 else: signals[dt] 0 return signals14utils/metrics.pyimport pandas as pd import numpy as np def max_drawdown(series): roll series.cummax() dd series / roll - 1 return dd.min() def sharpe_ratio(series, freq252): ret series.pct_change().dropna() return ret.mean() / (ret.std() 1e-8) * np.sqrt(freq)15main.py总入口from data.data_collector import DataCollector from factor.factor_calculator import FactorCalculator from strategy.strategy_engine import StrategyEngine from backtest.backtester import Backtester from backtest.multi_backtest import MultiBacktester from backtest.overfit_check import OverfitChecker from factor_analyze.ic_ir import ICIRAnalyzer from portfolio.optimizer import PortfolioOptimizer from monitor.notifier import Notifier from monitor.scheduler import TaskScheduler from utils.metrics import * from config import * def daily_strategy_task(): print( 每日量化任务运行 ) codes [600000,600036,601318] data DataCollector.batch_get_daily(codes, START_DATE, END_DATE) signals {} for code, df in data.items(): df FactorCalculator.tech_factors(df) signals[code] StrategyEngine.dual_factor_signal(df) bt Backtester() eq bt.run(data, signals) print(最终净值:, eq.iloc[-1]) print(最大回撤:, max_drawdown(eq)) Notifier.wechat(f量化信号完成\n净值{eq.iloc[-1]:.0f}) def main(): # 1. 运行回测 daily_strategy_task() # 2. 启动定时任务 sch TaskScheduler() sch.add_daily_job(daily_strategy_task, 15, 10) print(系统运行中按 CtrlC 退出) while True: import time time.sleep(1) if __name__ __main__: main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2476187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…