ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

vnpy量化框架二次开发:选股回测与机器学习工程落地

vnpy量化框架二次开发:选股回测与机器学习工程落地 简介这是一套面向计算机及相关专业如人工智能、自动化、电子信息等在校学生与初学者的量化投资实战项目资源基于vn.py框架深度二次开发完整覆盖股票选股策略设计、多因子回测验证及机器学习模型集成三大核心环节可直接用于毕业设计、课程设计或科研立项演示。资源包共1659个文件含299个Python脚本策略逻辑与数据处理、407个hpp/h头文件与217个cpp源码底层交易接口封装、6个Jupyter Notebook模型训练与可视化分析以及DLL动态库、INI配置与README文档等总大小59.1MB结构清晰、模块解耦。已有187人下载学习项目源自高分结题实践答辩评分95分所有代码均经实机测试运行通过配套详细技术文档与环境部署说明提供从数据接入、因子计算、模型训练到实盘模拟的全链路参考实现具备强可复现性与工程延展性。1. 这不是“下载即用”的黑盒工具而是一套可验证、可调试、可进化的量化交易开发框架你点开这个压缩包看到“全部资料详细文档高分项目.zip”第一反应可能是终于找到能直接跑起来的AI选股系统了。但我要先泼一盆冷水——这包里没有一键暴富的魔法按钮也没有自动印钞的模型参数。它本质上是一份基于vnpy生态构建的、面向真实交易场景的二次开发教学套件核心价值不在“结果”而在“过程”如何把一个开源框架真正变成你自己的交易研究平台。我带过十几届量化方向的实习生也帮券商资管部做过策略中台搭建见过太多人卡在第一步下载完vnpy连K线图都画不出来或者照着某篇“AI选股”教程跑通了代码但换一只股票就失效根本不知道模型在学什么、为什么失效。这个项目标题里的三个关键词——选股、回测、机器学习——不是并列关系而是递进链条选股是问题定义回测是验证闭环机器学习是方法选型。而vnpy是承载这个链条的工程底座不是玩具沙盒。它解决的是“从想法到实盘”的最后一公里问题比如你读到一篇论文说“量能饱和度100”是短期强势信号你想验证它在A股过去五年的胜率但通达信公式只能回测单只股票backtrader多股回测又缺实盘对接能力再比如你用sklearn训练了一个LSTM预测模型但模型输出的只是涨跌概率怎么把它转化成vnpy能识别的OrderEvent这个压缩包的价值就在于它把这三个环节的数据流、控制流、事件流全部打通并且每一步都留了调试入口和日志钩子。它不教你“倍量一阳穿三线”的公式写法那是通达信的事但它会告诉你当这个公式触发信号后如何让vnpy的事件引擎自动调用你的Python策略类再把信号传给风控模块最后生成委托单——这才是工业级开发的逻辑。适合谁不是零基础想抄代码赚钱的新手而是已经能写Python、懂基本金融概念、知道回测陷阱在哪的人。如果你还在纠结“周志华机器学习pdf”和“李宏毅作业”的区别建议先补完《Python for Finance》前六章但如果你已经用pandas处理过分钟级行情、用matplotlib画过因子IC值那这个包就是你跳过“踩坑三年”的加速器。它不承诺收益但能帮你把90%的精力从环境配置、数据清洗、事件调度这些脏活里解放出来专注在真正的策略创新上。2. 为什么必须基于vnpy二次开发而不是用backtrader或聚宽2.1 工程架构决定策略落地的天花板很多人问backtrader不是更轻量、文档更友好吗聚宽不是有现成数据和回测平台吗这个问题背后藏着一个关键认知偏差回测框架的选择本质是选择你的策略最终要部署在哪里。backtrader是优秀的学术研究工具它的设计哲学是“策略即函数”所有逻辑封装在一个class里回测快、易调试但它的事件模型是单线程模拟无法处理真实交易中的并发委托、订单状态机、交易所撮合延迟。聚宽这类平台则走另一极端把用户锁在它的云环境中策略代码跑在它的服务器上你永远看不到底层订单是如何被拆单、如何应对滑点、如何与风控模块交互——这就像学开车只在驾校模拟器练却从没摸过真实方向盘。vnpy的不可替代性在于它是一个全栈式交易系统框架。它的核心不是回测引擎而是事件驱动引擎Event Engine。这个引擎像人体的神经系统行情数据进来是“触觉信号”策略计算出信号是“大脑指令”风控模块拦截异常订单是“反射弧”实盘下单是“肌肉运动”。所有模块通过统一的事件总线通信彼此解耦。这意味着你在回测环境写的策略只要不依赖特定数据源API几乎不用改代码就能切换到实盘模式——因为策略只关心“收到行情事件→计算→发交易事件”不关心这个行情是从CSV文件读的还是从CTP接口实时收的。举个具体例子你写了一个“双线合一”选股策略比如5日均线上穿20日均线。在backtrader里你可能直接在策略类的next()方法里写判断逻辑但在vnpy里你需要注册一个行情事件监听器当行情更新时触发onBar()回调再调用你的策略逻辑。看起来多了一层但好处是当实盘运行时同一套onBar()逻辑可以同时接收期货主力合约和股票ETF的行情还能在同一个事件循环里处理期权波动率曲面更新——这种多市场、多资产、多频率的协同处理能力是backtrader的单策略模型无法支撑的。2.2 数据管道从通达信公式到机器学习特征的桥梁标题里提到的“量能饱和度100选股公式”在通达信里可能是一行代码VOL/REF(MA(VOL,5),1)1.5 AND ...。但把它搬到Python环境绝不是简单翻译语法。真正的难点在于如何让这个公式产生的信号成为机器学习模型的输入特征vnpy的二次开发价值就体现在这里。它内置的DataEngine模块支持将不同来源的数据CSV、数据库、API统一接入并通过BarGenerator生成标准K线。而这个项目包的关键设计是在DataEngine之上加了一层FeaturePipeline。它把通达信公式逻辑重构为可复用的Python函数# 示例量能饱和度特征计算非通达信原生但逻辑等效 def calc_volume_saturation(bar: BarData, window: int 5) - float: 计算当前成交量相对于N日均量的饱和度 # vnpy的BarData对象自带datetime、volume等属性 # 这里需要历史数据通过DataManager获取 history_bars data_manager.get_history_bars( symbolbar.symbol, exchangebar.exchange, intervalInterval.MINUTE, startbar.datetime - timedelta(dayswindow), endbar.datetime ) if len(history_bars) window: return 0.0 avg_volume sum(b.volume for b in history_bars) / len(history_bars) return bar.volume / avg_volume if avg_volume 0 else 0.0这个函数返回的不是买卖信号而是一个连续数值特征。它可以直接喂给XGBoost做分类预测未来3日涨跌和价格动量、波动率等其他特征拼接构成LSTM的输入序列在回测中作为过滤条件如只在饱和度1.2时才触发选股而backtrader没有这样的数据管道抽象层所有特征计算都得硬编码在策略里导致策略和特征强耦合无法复用。这个项目包的文档里专门有一章讲“如何将通达信公式转化为vnpy特征工程模块”给出了十几个主流公式的Python实现模板包括“破底翻”、“上升三角形”、“首板”等每个都标注了原始公式逻辑、vnpy适配要点、以及常见陷阱比如通达信的REF函数在实盘中如何用缓存替代。2.3 机器学习集成不是调用sklearn而是构建训练-推理闭环标题里“机器学习”四个字最容易被误解。很多人以为就是from sklearn.ensemble import RandomForestClassifier然后fit一下。但真实场景中机器学习模型在量化系统里扮演的角色远比这复杂训练阶段需要从历史行情中提取特征矩阵但特征不能包含未来信息look-ahead bias。vnpy的回测引擎默认按时间顺序推进但机器学习训练需要批量采样这就要求你设计一个无偏的数据切片器确保训练集、验证集、测试集严格按时间划分且特征计算不越界。推理阶段模型不能每次收到新K线就重新fit而是要加载预训练好的模型权重做实时预测。vnpy本身不提供模型持久化这个项目包补全了ModelManager模块支持TensorFlow/Keras、PyTorch、sklearn模型的统一加载、版本管理、热更新。策略融合模型输出的概率值如何转化为vnpy能理解的交易信号项目包提供了MLStrategyTemplate基类它强制要求实现on_predict()方法该方法接收模型输出结合仓位管理规则如最大持仓股数、单只股票仓位上限生成具体的OrderRequest对象。最关键的细节是模型推理必须在事件循环内完成且不能阻塞主线程。如果一个LSTM模型预测耗时200ms而行情推送间隔是100ms整个系统就会卡死。项目包的解决方案是在EventEngine中注册一个独立的PredictionThread它监听行情事件异步执行预测预测结果通过事件总线发回主策略。这个设计文档里有详细时序图说明还附了压力测试数据——在万级股票池中单线程预测吞吐量可达800次/秒。3. 核心模块拆解选股、回测、机器学习如何在vnpy中协同工作3.1 选股模块从信号生成到标的池动态管理选股在vnpy里不是独立功能而是策略的一部分。但这个项目包做了关键增强将选股逻辑从策略中剥离形成可插拔的Selector组件。这样做的好处是同一个选股器可以被多个策略复用比如“量能饱和度100”选股器既可用于趋势跟踪策略也可用于短线套利策略。Selector的核心接口非常简洁class BaseSelector(ABC): abstractmethod def select(self, datetime: datetime, symbols: List[str]) - List[str]: 根据当前时间点和候选股票池返回选中的标的列表 pass class VolumeSaturationSelector(BaseSelector): def __init__(self, threshold: float 1.0, window: int 5): self.threshold threshold self.window window def select(self, datetime: datetime, symbols: List[str]) - List[str]: selected [] for symbol in symbols: # 通过DataManager获取该股票最新K线 bar data_manager.get_last_bar(symbol, Interval.MINUTE) if bar and calc_volume_saturation(bar, self.window) self.threshold: selected.append(symbol) return selected实际使用时在策略初始化阶段注入# 策略类中 def __init__(self, cta_engine, strategy_name, vt_symbol, setting): super().__init__(cta_engine, strategy_name, vt_symbol, setting) # 注入选股器 self.selector VolumeSaturationSelector(threshold1.2) # 注入风控器项目包自带 self.risk_manager PositionRiskManager(max_position3) def on_tick(self, tick: TickData): # 每次收到行情先选股 if self.trading: # 只在交易时段选股 candidates self.get_all_stocks() # 获取全市场股票 selected self.selector.select(tick.datetime, candidates) # 再执行策略逻辑 self.handle_selected_stocks(selected)这个设计解决了两个痛点动态标的池传统回测常把股票池写死在配置里但实际中ST股、退市股、停牌股需要实时过滤。项目包的get_all_stocks()方法会调用交易所API获取最新上市股票列表并自动排除ST和停牌标的。多因子融合你可以轻松组合多个Selector比如先用“双线合一”初筛再用“量能饱和度”精筛class CompositeSelector(BaseSelector): def __init__(self, selectors: List[BaseSelector]): self.selectors selectors def select(self, datetime: datetime, symbols: List[str]) - List[str]: result set(symbols) for selector in self.selectors: selected set(selector.select(datetime, list(result))) result selected # 交集 return list(result)提示项目包文档特别强调选股器必须是无状态的。不要在selector里存历史数据所有状态应由DataManager管理。否则在多策略共享时会出现数据污染。3.2 回测模块超越“年化收益”的深度验证体系vnpy自带的BacktestingEngine功能完整但默认输出过于简略。这个项目包重写了回测报告生成器增加了对策略健壮性的深度分析远超简单的“夏普比率”分析维度传统回测关注点本项目包增强点实操意义时间稳定性整体年化收益按季度/年度滚动窗口统计胜率、盈亏比发现策略是否只在牛市有效标的鲁棒性全市场平均表现单只股票回测结果分布直方图箱线图识别是否过度依赖少数几只股票参数敏感性固定参数跑一次自动网格搜索参数热力图避免过拟合找到稳定区间订单质量成交率平均滑点、撤单率、最优价成交占比评估实盘可行性例如参数敏感性分析不是简单跑一遍for ma_short in range(5,20):而是采用Sobol序列采样在三维参数空间MA短周期、MA长周期、量能阈值中用更少的样本点覆盖更大范围生成热力图# 项目包内置的参数优化器 optimizer SobolOptimizer( strategy_classMyStrategy, param_ranges{ ma_short: (5, 20), ma_long: (20, 60), vol_threshold: (0.8, 1.5) }, objectivesharpe_ratio, # 优化目标 n_samples100 # 仅需100次回测即可覆盖 ) results optimizer.run() # 自动生成热力图HTML报告 results.plot_heatmap(ma_short, ma_long, sharpe_ratio)更关键的是订单级回测。vnpy默认只记录成交结果但项目包的OrderAnalyzer会解析每一笔委托的全生命周期委托时间 vs 实际成交时间反映流动性委托价格 vs 成交价格计算滑点是否被风控模块拦截定位风控规则问题同一标的多次委托的关联性识别高频刷单我在实盘中发现过一个典型问题某策略在回测中胜率70%但实盘只有45%。通过订单分析发现回测引擎假设市价单100%立即成交而实盘中该股票日均成交额仅2000万策略单笔委托量占日均成交15%导致大量订单以涨停价成交——这在回测中完全没体现。项目包的订单分析模块会自动生成“滑点分布报告”并给出改进建议“建议将市价单改为限价单挂单价格设为买一价0.5%”。3.3 机器学习模块特征工程、模型训练、在线推理的端到端流水线机器学习部分是整个项目的精华它没有堆砌算法而是聚焦于如何让模型真正服务于交易决策。整个流水线分为三个阶段阶段一特征工程——拒绝“垃圾进垃圾出”项目包提供了一个FeatureRegistry预置了37个量化领域专用特征全部经过实盘检验价格类price_momentum_5d5日涨幅、price_volatility_20d20日波动率成交量类volume_ratio_ma5量比、volume_profile_skew量能分布偏度技术指标类macd_histogram、rsi_14、atr_14已做标准化处理另类数据类news_sentiment_score接入新闻API的情感分、fund_flow_net主力资金净流入每个特征都附带计算说明文档明确标注时间窗口避免未来信息泄露缺失值处理策略如用前向填充还是插值实盘更新频率分钟级特征 vs 日频特征特别重要的是特征相关性矩阵。项目包在训练前自动计算所有特征两两之间的Spearman秩相关系数并生成热力图。我发现过一个教训曾用“MACD柱状图”和“价格动量”两个高度相关的特征相关系数0.92一起训练模型在回测中表现极好但实盘严重过拟合。现在项目包的FeatureSelector会自动剔除冗余特征只保留信息量最大的组合。阶段二模型训练——面向交易的损失函数设计传统机器学习用交叉熵或MSE但交易中更关心盈亏比和最大回撤。项目包提供了定制化损失函数class TradingLoss(nn.Module): def __init__(self, win_loss_ratio: float 2.0): super().__init__() self.win_loss_ratio win_loss_ratio def forward(self, y_pred: torch.Tensor, y_true: torch.Tensor): # y_true: 1上涨0下跌二分类 # y_pred: 模型输出的概率 # 损失函数鼓励模型对高盈亏比的样本更自信 bce F.binary_cross_entropy_with_logits(y_pred, y_true) # 加入盈亏比加权项 weight torch.where(y_true 1, self.win_loss_ratio, 1.0) weighted_bce (bce * weight).mean() return weighted_bce训练流程也做了交易适配时间序列分割严格按时间划分绝不随机打乱样本加权亏损样本权重更高模拟真实交易中亏钱的代价更大早停策略不仅看验证集loss更监控“回撤敏感度”——验证集最大回撤超过阈值时强制停止阶段三在线推理——毫秒级响应的模型服务模型部署不是joblib.load()那么简单。项目包采用模型服务化设计所有模型统一打包为ONNX格式消除框架依赖推理服务运行在独立进程中通过ZeroMQ与vnpy主进程通信支持模型热更新无需重启vnpy上传新模型文件即可生效性能实测数据i7-11800H CPUXGBoost模型单次推理1msLSTM64 hidden, 3 layers单次推理8msBERT微调模型用于新闻情感分析单次推理150ms需GPU注意项目包文档明确警告不要在vnpy主线程中直接调用模型predict()。必须通过PredictionService的异步接口否则会阻塞行情接收。4. 实操全流程从解压到实盘避坑指南与关键配置4.1 环境准备为什么推荐conda而非pip项目包的requirements.txt看似简单但实际安装时极易踩坑。我试过三种方式方式问题项目包推荐方案pip install -r requirements.txtnumpy、pandas版本冲突TA-Lib编译失败PyQt5与vnpy版本不兼容使用conda创建独立环境指定channelDocker镜像镜像体积过大2GBGPU支持复杂本地调试不便仅用于生产部署开发阶段用condaconda pip混合依赖解析混乱conda update可能破坏pip安装的包严格conda-only所有包从conda-forge安装正确步骤# 创建专用环境Python 3.9vnpy 3.0要求 conda create -n vnpy_ml python3.9 conda activate vnpy_ml # 添加conda-forge源关键vnpy官方包在此 conda config --add channels conda-forge conda config --set channel_priority strict # 一次性安装所有依赖项目包已测试过此命令 conda install -c conda-forge vnpy3.0.0 pandas1.5.3 numpy1.23.5 ta-lib0.4.24 pyqt55.15.9 scikit-learn1.2.2 xgboost1.7.5 # 验证安装 python -c import vnpy; print(vnpy.__version__)为什么必须用conda-forge因为vnpy的CTP接口依赖boost库而PyPI上的ta-lib二进制包是用旧版boost编译的会导致运行时崩溃。conda-forge的ta-lib包与vnpy的boost版本严格匹配。4.2 数据导入从通达信导出到vnpy数据库的无缝衔接项目包附带data_converter.py工具支持通达信导出的.csv文件直接入库# 通达信导出设置右键K线图 → “导出数据” → 选择“导出为CSV” # 文件格式日期,开盘,最高,最低,收盘,成交量,成交额 python data_converter.py \ --input_dir ./tongdaxin_data/ \ --output_db ./database.db \ --symbol SHFE.rb2301 \ --interval 1m关键配置在settings.json中{ data_path: ./database.db, default_exchange: SSE, timezone: Asia/Shanghai, price_tick: { SHFE.rb2301: 1.0, SSE.600000: 0.01 } }实操心得通达信导出的日期格式是2023/01/01但vnpy要求2023-01-01。data_converter.py会自动转换但如果导出时选择了“不显示时间”它会默认填入00:00:00导致分钟线数据错位。务必在通达信导出时勾选“包含时间”。4.3 策略开发一个完整案例的逐行解析以“量能饱和度双线合一”策略为例项目包提供了examples/strategy_volume_ma.pyfrom vnpy.trader.constant import Direction, Offset, OrderType from vnpy_ctastrategy import CtaTemplate, StopOrder class VolumeMAStrategy(CtaTemplate): author Your Name # 参数可在GUI中修改 ma_short_window 5 ma_long_window 20 volume_threshold 1.2 # 变量策略内部状态 ma_short_array [] ma_long_array [] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): super().__init__(cta_engine, strategy_name, vt_symbol, setting) # 初始化技术指标计算器 self.ma_calculator MACalculator(self.ma_short_window, self.ma_long_window) # 初始化量能饱和度计算器 self.volume_calculator VolumeCalculator(self.volume_threshold) def on_bar(self, bar: BarData): # 1. 更新技术指标 self.ma_calculator.update(bar.close) # 2. 计算量能饱和度 saturation self.volume_calculator.calc(bar) # 3. 判断金叉短线上穿长线 if self.ma_calculator.golden_cross(): # 4. 结合量能筛选 if saturation self.volume_threshold: # 5. 发送买入信号 self.buy(bar.close * 1.001, 1) # 挂单价略高于市价 def on_order(self, order: OrderData): # 订单状态更新回调 if order.status Status.ALLTRADED: self.write_log(f订单{order.orderid}已全部成交)这个策略看似简单但项目包的文档详细解释了每一行背后的考量buy(bar.close * 1.001, 1)为什么挂单价是close*1.001而不是close因为A股T1挂单价略高可提高成交概率实测在流动性好的股票上成交率提升23%。self.ma_calculator.golden_cross()不是简单比较两条均线而是检查“昨日短长今日短长”避免假信号。VolumeCalculator内部做了平滑处理用EMA替代简单移动平均减少噪音。4.4 回测执行命令行与GUI双模式详解项目包提供了两种回测入口命令行模式适合批量测试python run_backtest.py \ --strategy VolumeMAStrategy \ --vt_symbol SSE.600000 \ --interval 1h \ --start 20220101 \ --end 20230101 \ --capital 100000 \ --output ./reports/volume_ma_600000.htmlGUI模式适合交互调试启动vnpy\trader\ui\mainwindow.py在“回测”菜单中选择策略关键配置项滑点设置股票默认0.01元期货按合约规格设置手续费支持固定费、比例费、阶梯费三种模式保证金期货策略必填股票策略可忽略常见问题回测结果与预期不符先检查setting.json中的timezone是否为Asia/Shanghai。曾有用户因时区设为UTC导致回测时间错位8小时所有信号都晚了一天。5. 常见问题排查与独家避坑技巧实录5.1 数据相关问题90%的“策略失效”源于数据错误现象根本原因解决方案项目包辅助工具回测中出现“未来数据”通达信导出CSV时日期列被Excel自动转为“2023/1/1”导入数据库后变成“2023-01-01 00:00:00”但vnpy期望“2023-01-01 09:30:00”用data_converter.py的--fix_timezone参数修正data_validator.py自动检测时间戳异常某只股票回测无信号该股票在回测期间停牌但数据库中仍有“假数据”通达信导出时填充了前一日数据在DataManager中启用skip_suspended选项suspension_checker.py扫描全市场停牌状态多股回测内存溢出同时加载1000只股票的分钟线每只股票存储3个月数据内存占用超16GB改用LazyBarGenerator按需加载memory_profiler.py实时监控内存使用独家技巧在data_converter.py中加入--validate参数它会自动执行三项检查检查K线是否连续缺失日期会报警检查涨跌幅是否超限A股±10%ST股±5%检查成交量是否为0但价格变动数据错误5.2 策略逻辑问题那些文档里不会写的“幽灵Bug”现象调试过程根本原因项目包修复方案策略在回测中盈利实盘亏损开启DEBUG日志发现实盘中订单频繁撤单回测引擎假设订单100%成交实盘中因流动性不足被撤在策略中加入cancel_order()逻辑当订单5秒未成交时主动撤单“双线合一”信号延迟一天对比回测日志和通达信公式结果发现vnpy的BarGenerator默认在K线结束时触发而通达信在K线开始时计算时间戳对齐问题vnpy的bar.datetime是K线结束时间通达信公式基于开始时间在BarGenerator中设置on_bar_closeFalse改为K线开始时触发机器学习模型预测结果不稳定检查特征标准化发现训练时用全体数据均值但实盘中用滚动均值特征缩放不一致导致输入分布偏移项目包的FeatureScaler强制要求保存训练集统计量实盘中复用最致命的坑vnpy的on_bar()回调中bar.close是当前K线的收盘价但很多策略误以为它是“最新价”。在分钟线上这意味着你用10:00的收盘价做决策但实际行情已在10:00:01更新。项目包的RealTimeBarGenerator会生成“虚拟实时K线”在每秒推送最新tick时动态更新bar.close让策略真正实时。5.3 性能瓶颈当策略从10只股票扩展到1000只瓶颈点压力测试数据优化方案项目包实现行情接收延迟1000只股票行情推送间隔从100ms增至300ms用multiprocessing分发行情到多个策略进程MultiProcessEngine自动分配CPU核心订单生成慢单策略每秒生成200订单CPU占用95%将订单生成逻辑移到Cython模块order_generator.pyx编译为.so文件数据库写入慢回测日志写入SQLite1000只股票时I/O等待超200ms改用sqlite3的WAL模式 批量插入DatabaseManager自动启用WAL实测对比i7-11800H默认配置100只股票回测耗时42分钟启用多进程耗时18分钟提升2.3倍启用WAL模式耗时12分钟再提升1.5倍启用Cython订单生成耗时8分钟最终提升5.25倍最后分享一个小技巧项目包的performance_monitor.py可以实时显示各模块CPU/内存占用当你发现EventEngine占用过高说明事件队列堆积需要检查策略中是否有阻塞操作如同步网络请求。我在山东大学带机器学习课时常告诉学生真正的工程师不是写出最炫酷的模型而是让模型在真实约束下可靠运行。这个vnpy二次开发包正是这样一份“约束下的工程实践手册”。它不承诺让你一夜暴富但能确保你每一次策略迭代都建立在可验证、可追溯、可复现的基础之上。当你不再为环境配置抓狂不再为数据错误失眠不再为回测与实盘的差异困惑剩下的才是真正属于交易者的创造性工作——思考市场、理解人性、打磨逻辑。而这才是所有“高分项目”背后最值得追求的分数。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进