ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ChatGPT大模型选股与夏普比率组合优化系统实战

ChatGPT大模型选股与夏普比率组合优化系统实战 1. 从一条标题说起这套系统到底在解决什么问题第一次看到“ChatGPT大模型荐股与夏普比率投资组合优化系统”这个标题我脑子里冒出来的第一个念头是又是一个拿大模型当噱头的东西。但仔细拆开看这个项目其实踩中了两个非常实在的痛点——一是普通人面对几千只标的根本不知道从哪看起二是就算选出了几只也不知道怎么分配仓位才能让收益和风险达到一个舒服的平衡。这套系统做的事情说白了就是用大模型充当一个“研究助理”的角色帮你从海量信息里筛出值得关注的标的然后再用夏普比率这个经典指标把选出来的标的组合成一个风险调整后收益尽可能高的投资组合。它不是一个“告诉你买什么就能暴富”的黑盒而是一个把大模型的文本理解能力和经典量化金融工具串起来的辅助决策流水线。适合谁来参考如果你有一点Python基础对量化投资感兴趣想搞明白大模型怎么跟传统金融模型结合那这套东西非常适合你拿来练手和改造。如果你是完全零基础的小白也没关系我会把每个环节的原理和操作都拆开讲清楚你照着搭一遍至少能理解整个链路是怎么跑通的。需要提前说明的是这个项目的定位是“辅助研究工具”不是投资建议生成器。大模型的输出存在不确定性夏普比率的计算也高度依赖历史数据的质量和时间窗口的选择。我见过太多人拿着一个回测曲线漂亮的策略就觉得自己找到了圣杯结果实盘一跑就傻眼。所以心态要摆正这套系统的价值在于帮你提高研究效率、拓宽信息覆盖面而不是替你做出最终决策。2. 整体架构设计为什么这样搭2.1 三层架构的拆解逻辑这套系统的架构我把它分成三层数据层、智能层、优化层。每一层各司其职层与层之间通过标准化的数据接口通信这样任何一层想换实现方式都不会影响其他层。数据层负责搞定原始数据。股票的基础行情数据、财务指标、新闻资讯、研报摘要这些都属于数据层的范畴。我选择用本地缓存加定时更新的方式而不是每次跑都去实时拉取。原因很简单大模型的调用是有成本的如果你每次调试都重新拉一遍数据、重新跑一遍模型时间和金钱都扛不住。本地缓存让你可以反复调试优化层的逻辑而不用反复消耗模型调用额度。智能层是整个系统的核心也是“ChatGPT大模型”发挥作用的地方。这一层做的事情是接收数据层传来的原始信息通过精心设计的提示词让大模型输出结构化的选股逻辑和候选标的列表。注意这里的关键词是“结构化”。如果你直接问大模型“给我推荐几只股票”它大概率会给你一堆模棱两可、无法验证的回答。但如果你把任务拆解成“分析以下财务数据判断哪些标的的营收增速和利润率组合处于行业前30%”大模型的输出就会具体得多。优化层拿到智能层输出的候选标的列表后开始做真正的数学计算。夏普比率的公式本身不复杂组合预期收益率 - 无风险利率/ 组合收益率标准差。但难点在于你需要用历史数据估算每只标的的预期收益率和协方差矩阵然后通过优化算法找到一组权重使得夏普比率最大化。这一层我选择用scipy.optimize里的minimize函数来实现因为它的SLSQP方法对带约束的优化问题处理得比较稳。2.2 为什么选夏普比率而不是其他指标有人可能会问为什么是夏普比率而不是索提诺比率、卡玛比率或者信息比率这个问题我在设计阶段也纠结过。夏普比率的优势在于它的普适性和直观性。它衡量的是每承担一单位总风险你能获得多少超额回报。这个逻辑非常干净不需要你对下行风险做额外假设也不需要指定基准指数。索提诺比率只考虑下行波动理论上更符合投资者对“风险”的直觉但它需要你设定一个最低可接受收益率这个参数的选择本身就带有主观性。卡玛比率用最大回撤代替标准差对极端行情的敏感度更高但最大回撤的计算高度依赖回测区间的选择换一个时间段结果可能天差地别。信息比率需要你选定一个基准而基准的选择又会引入新的偏差。夏普比率虽然也有它的局限——比如它假设收益率服从正态分布而实际市场经常出现肥尾——但作为一套辅助研究系统的核心指标它的可解释性和可复现性是最好的。你告诉别人“我这个组合的夏普比率是1.8”对方立刻就能理解这意味着什么。你告诉别人“我这个组合的索提诺比率是2.3”对方可能还得先问一句“你设的最低可接受收益率是多少”。2.3 Agent在整个链路中的角色定位标题里提到了“agent”这个词现在被用得有点泛滥。在这套系统里Agent的角色是一个任务调度器和结果校验器。它不直接参与选股决策也不直接做数学优化而是负责协调数据层、智能层、优化层之间的调用顺序并在关键节点做合理性检查。举个例子当智能层输出候选标的列表后Agent会检查这个列表是否满足预设的约束条件——比如标的数量是否在5到20只之间、是否覆盖了至少3个不同的行业、是否有标的的财务数据缺失。如果检查不通过Agent会触发重试逻辑调整提示词后重新调用大模型。这个校验环节看起来不起眼但实际跑起来能帮你省掉大量因为脏数据导致的调试时间。我用的Agent框架比较轻量没有上那些重型的工作流引擎。核心就是一个while循环加上状态机每个状态对应一个处理函数状态之间的跳转条件写清楚就行。这样做的好处是调试直观出问题了直接看状态日志就能定位到是哪一步卡住了。3. 数据准备与预处理脏数据比没数据更可怕3.1 数据源的选取与获取方式数据源这块我试过几种方案。免费的数据接口有yfinance、akshare这些优点是零成本缺点是稳定性和字段完整性参差不齐。付费的数据服务比如Wind、聚宽数据质量高但成本也高。对于个人练手项目我的建议是先用免费接口把流程跑通等策略逻辑验证得差不多了再考虑要不要升级数据源。具体到这套系统我需要的核心数据包括日频行情数据开盘价、收盘价、最高价、最低价、成交量、财务指标营收、净利润、ROE、资产负债率、以及新闻文本数据。行情数据用来计算收益率和协方差矩阵财务指标用来做基本面筛选新闻文本用来喂给大模型做情绪分析和事件驱动判断。获取方式上我写了一个DataFetcher类内部封装了不同数据源的适配逻辑。每个数据源实现统一的fetch接口返回标准化的DataFrame。这样如果某个数据源挂了换一个实现就行上层代码不用动。class DataFetcher: def __init__(self, sourceakshare): self.source source def fetch_price(self, symbols, start_date, end_date): if self.source akshare: import akshare as ak df ak.stock_zh_a_hist(symbolsymbols, perioddaily, start_datestart_date, end_dateend_date) return self._standardize(df) def _standardize(self, df): df.columns [date, open, close, high, low, volume, amount, amplitude, pct_change, change, turnover] df[date] pd.to_datetime(df[date]) return df.set_index(date).sort_index()3.2 数据清洗的五个关键步骤拿到原始数据后千万别直接往模型里灌。我踩过的坑包括停牌期间的数据缺失导致收益率计算出inf、除权除息没处理导致价格序列出现跳空、不同数据源的日期对齐不一致导致合并后出现大量NaN。下面是我总结的清洗流程第一步处理停牌和缺失值。对于停牌日我选择用前一个交易日的收盘价填充同时打上一个is_suspended标记。这样在计算收益率时停牌日的收益率就是0不会污染协方差矩阵的估计。如果一只标的连续停牌超过20个交易日我会直接把它从候选池里剔除。第二步复权处理。必须用后复权价格来计算收益率否则除权除息日会出现巨大的假跌。akshare的接口默认返回的是不复权价格需要手动调用复权因子进行换算。这一步如果偷懒不做回测出来的收益率会严重失真。第三步日期对齐。不同标的的交易日历可能略有差异我统一用所有标的交易日的并集作为主索引缺失值用前向填充处理。注意前向填充只适用于价格数据对于成交量数据填充0更合理。第四步异常值检测。单日涨跌幅超过20%的非涨跌停限制导致的我会标记为异常值并人工核查。有时候是数据源错误有时候是真实的重组事件需要区别对待。第五步标准化字段命名。不同数据源返回的列名五花八门我统一映射成open、close、high、low、volume这五个标准字段后面所有代码都基于这套命名来写。提示数据清洗的代码一定要写单元测试。我一开始觉得这是浪费时间后来有一次因为复权因子没对齐导致整个回测结果完全错误排查了一整天才发现问题。从那以后每个清洗步骤我都写了断言检查。3.3 新闻文本数据的处理要点新闻数据这块大模型是天然的处理工具但前提是你得把文本整理成模型能理解的格式。我的做法是每条新闻提取标题、发布时间、来源、正文摘要四个字段然后按标的代码分组每个标的取最近30天的新闻拼接成一段不超过2000字的文本块。这里有个细节新闻的时效性很重要。三个月前的利好新闻和昨天的利好新闻对当前决策的参考价值完全不同。所以我在拼接文本时会按时间倒序排列并且在每条新闻前面加上日期标记让模型自己判断时效性。另外新闻来源的可信度也需要考虑。我维护了一个来源权重表权威财经媒体的新闻权重设为1.0自媒体平台的设为0.5论坛帖子的设为0.2。这个权重不直接喂给模型而是在后期做信号聚合时使用。4. 大模型选股模块提示词工程是核心中的核心4.1 提示词设计的四层结构大模型选股的效果九成取决于提示词的质量。我经过反复迭代最终稳定下来的提示词结构包含四层角色设定、任务描述、数据输入、输出格式约束。角色设定层告诉模型“你是谁”。我用的设定是“你是一名拥有15年经验的股票研究员擅长从财务数据和新闻信息中识别被市场低估的标的。”这个设定不是随便写的它会影响模型回答的风格和侧重点。如果你设定成“你是一名短线交易员”模型给出的回答会更偏向技术面和市场情绪设定成“价值投资者”模型会更关注基本面和估值。任务描述层要具体到可执行。不要写“帮我选几只股票”而要写“根据以下财务数据和新闻摘要筛选出满足以下条件的标的最近两个季度营收同比增速大于15%、净利润率为正且环比改善、所属行业处于政策支持方向、最近30天无重大负面新闻”。数据输入层就是把清洗好的数据按固定格式拼进提示词。我用的格式是JSON因为模型对JSON结构的理解比较稳定。每个标的作为一个对象包含symbol、financials、news_summary三个字段。输出格式约束层最关键。我要求模型输出一个JSON数组每个元素包含symbol、reason、confidence三个字段。confidence是0到1之间的浮点数表示模型对这个选择的信心程度。这个字段在后面做组合优化时可以作为权重调整的参考。PROMPT_TEMPLATE 你是一名拥有15年经验的股票研究员擅长从财务数据和新闻信息中识别被市场低估的标的。 任务根据以下数据筛选出满足条件的标的。 筛选条件 1. 最近两个季度营收同比增速大于15% 2. 净利润率为正且环比改善 3. 最近30天无重大负面新闻 数据 {data_json} 输出要求 返回一个JSON数组每个元素包含 - symbol: 标的代码 - reason: 选择理由不超过100字 - confidence: 信心程度0到1之间的浮点数 只返回JSON不要有其他内容。 4.2 温度参数与输出稳定性的权衡大模型的temperature参数控制输出的随机性。温度越高输出越多样但越不稳定温度越低输出越确定但可能过于保守。我在这个项目里用的是0.3这是一个经过多次试验后找到的平衡点。为什么不是0因为完全确定性的输出意味着每次跑出来的候选列表一模一样失去了大模型“多角度分析”的优势。为什么不是0.7以上因为温度太高时模型会开始“编造”数据里不存在的财务指标或者给出逻辑上自相矛盾的理由。0.3这个值既能保证每次输出有细微差异相当于多个分析师从不同角度给你建议又不会偏离数据太远。还有一个技巧我会对同一个输入跑三次模型调用然后取三次输出的交集作为最终候选列表。这样做的好处是过滤掉那些偶然性较强的选择。如果某个标的在三次调用中都被选中说明模型对它的判断比较稳定如果只出现一次可能是随机波动导致的直接剔除。4.3 大模型输出的校验与后处理模型输出JSON后不能直接信。我见过模型返回不完整JSON、字段名拼写错误、confidence值超出0到1范围等各种情况。所以必须加一层校验import json def validate_output(raw_output): try: data json.loads(raw_output) except json.JSONDecodeError: return None if not isinstance(data, list): return None validated [] for item in data: if not all(k in item for k in [symbol, reason, confidence]): continue if not isinstance(item[confidence], (int, float)): continue if not 0 item[confidence] 1: item[confidence] max(0, min(1, item[confidence])) validated.append(item) return validated if validated else None校验不通过时Agent会触发重试逻辑把原始输出和错误信息一起拼进新的提示词让模型自己修正。通常重试一次就能拿到合法输出如果连续三次都失败就跳过这次调用记录日志供后续排查。注意不要试图让模型输出过于复杂的嵌套结构。我一开始要求模型输出包含“看多理由”和“风险提示”两个子字段的嵌套JSON结果模型经常把两个字段的内容搞混。后来改成扁平结构每个字段只放一个字符串稳定性大幅提升。5. 夏普比率组合优化数学原理与代码实现5.1 夏普比率的计算逻辑与参数选择夏普比率的公式看起来简单但每个参数的选择都有讲究。收益率序列我用的是日频收益率计算方式是(今日收盘价 - 昨日收盘价) / 昨日收盘价。注意要用后复权价格前面已经强调过了。时间窗口我选的是过去252个交易日大约对应一年的交易日数量。为什么不是更长因为A股市场的风格切换比较快用三年前的数据来估计当前的协方差矩阵参考价值有限。为什么不是更短因为太短的时间窗口会导致协方差矩阵估计不稳定优化出来的权重会过度集中在一两只标的上。无风险利率我用的是一年期国债收益率按日折算。这个数据可以从公开渠道获取折算公式是(1 年化利率) ** (1/252) - 1。不要直接用年化利率除以252那样会有微小的复利误差。年化处理日频夏普比率需要年化才能跟其他策略比较。年化方式是乘以sqrt(252)。这个sqrt(252)来自收益率独立同分布的假设虽然实际市场不满足这个假设但作为行业惯例大家都这么用。5.2 协方差矩阵的估计与收缩方法直接用历史收益率计算协方差矩阵在标的数量较多时会出现估计误差累积的问题。举个例子如果你有20只标的协方差矩阵有20×20400个元素需要估计但你的样本只有252天估计误差会很大。这会导致优化算法给出极端权重——比如把90%的仓位压在一只标的上。我用的解决方案是Ledoit-Wolf收缩估计。它的核心思想是把样本协方差矩阵向一个结构化的目标矩阵“收缩”目标矩阵通常是对角矩阵假设标的之间不相关。收缩强度由一个系数控制这个系数通过最小化估计误差的期望值来确定。from sklearn.covariance import LedoitWolf def estimate_covariance(returns_df): lw LedoitWolf() lw.fit(returns_df) return lw.covariance_实测下来用了收缩估计后优化出来的权重分布明显更均匀不会出现单只标的权重超过40%的情况。代价是组合的样本内夏普比率会略微降低但样本外的稳定性提升明显。这个取舍我觉得很值。5.3 带约束的权重优化实现优化问题的数学形式是最大化(w^T * mu - rf) / sqrt(w^T * Sigma * w)约束条件是权重之和为1、每个权重在0到1之间不允许做空、单只标的权重不超过20%。这个优化问题是非凸的因为目标函数里有权重的平方根。但通过变量替换可以转化成凸优化问题。不过在实际操作中我直接用scipy.optimize.minimize来解把最大化夏普比率转化成最小化负夏普比率import numpy as np from scipy.optimize import minimize def optimize_portfolio(mu, cov, rf0.02, max_weight0.2): n len(mu) def neg_sharpe(weights): port_return np.dot(weights, mu) port_vol np.sqrt(np.dot(weights.T, np.dot(cov, weights))) return -(port_return - rf) / port_vol constraints [ {type: eq, fun: lambda w: np.sum(w) - 1} ] bounds tuple((0, max_weight) for _ in range(n)) init_weights np.array([1/n] * n) result minimize(neg_sharpe, init_weights, methodSLSQP, boundsbounds, constraintsconstraints, options{maxiter: 1000, ftol: 1e-9}) return result.x if result.success else None初始权重我用的是等权因为等权是一个比较“中性”的起点不容易陷入局部最优。maxiter设成1000是为了保证在标的数量较多时也能收敛。ftol设成1e-9是精度要求太小会导致迭代次数暴增太大则结果不够精确。5.4 优化结果的解读与调整优化出来的权重不能直接用。我一般会做两件事权重截断和再归一化。如果某只标的的权重小于2%我会直接把它剔除然后把剔除后的权重重新归一化。原因很简单2%的仓位对组合的影响微乎其微但会增加交易成本和跟踪难度。另外我会检查优化后的组合夏普比率是否显著高于等权组合。如果优化后的夏普比率只比等权高一点点比如0.05以内我会倾向于选择等权组合。因为优化带来的样本外收益往往没有样本内那么明显等权组合的鲁棒性更好。提示优化算法给出的权重是“样本内最优”不代表未来表现。我习惯把优化权重和等权权重各跑一遍样本外回测如果两者差异不大就选等权省心省力。6. Agent调度与系统集成让各模块跑起来6.1 Agent的状态机设计Agent的核心是一个状态机我定义了五个状态INIT、FETCH_DATA、LLM_SELECT、OPTIMIZE、REPORT。每个状态对应一个处理函数处理完成后根据返回结果决定下一个状态。class StockAgent: def __init__(self): self.state INIT self.data {} self.candidates [] self.weights None def run(self): while self.state ! DONE: if self.state INIT: self.state FETCH_DATA elif self.state FETCH_DATA: self.data self.fetch_data() self.state LLM_SELECT if self.data else ERROR elif self.state LLM_SELECT: self.candidates self.llm_select() self.state OPTIMIZE if self.candidates else ERROR elif self.state OPTIMIZE: self.weights self.optimize() self.state REPORT if self.weights is not None else ERROR elif self.state REPORT: self.generate_report() self.state DONE elif self.state ERROR: self.handle_error() self.state DONE这个状态机的好处是逻辑清晰每个状态的输入输出都明确。出问题的时候看日志就知道卡在哪个状态排查起来很快。6.2 错误处理与重试机制系统跑起来最怕的就是某个环节挂了导致整个流程中断。我的处理策略是可重试的错误自动重试不可重试的错误记录日志并跳过。数据拉取失败、模型调用超时、优化不收敛这些都属于可重试错误。我的重试策略是第一次失败后等5秒重试第二次失败后等15秒重试第三次失败后等45秒重试。三次都失败就放弃记录错误信息。数据格式错误、模型输出无法解析、优化约束冲突这些属于不可重试错误。遇到这类错误直接跳过当前标的或当前批次继续处理下一个。import time def retry_with_backoff(func, max_retries3, base_delay5): for attempt in range(max_retries): try: return func() except Exception as e: if attempt max_retries - 1: raise delay base_delay * (3 ** attempt) time.sleep(delay) return None6.3 结果输出与可视化最终的报告我生成两份一份是Markdown格式的文字报告包含候选标的列表、选择理由、优化权重、组合夏普比率等关键信息另一份是HTML格式的可视化报告用plotly画出权重分布饼图、历史净值曲线、回撤曲线。可视化这块我踩过一个坑plotly生成的HTML文件如果直接嵌入到其他页面里可能会有跨域加载的问题。后来我改成用plotly.io.to_html生成完整的HTML字符串然后直接写入文件这样就不依赖外部资源了。import plotly.graph_objects as go import plotly.io as pio def generate_weight_chart(symbols, weights): fig go.Figure(data[go.Pie(labelssymbols, valuesweights)]) fig.update_layout(title组合权重分布) return pio.to_html(fig, full_htmlFalse)7. 常见问题与排查技巧实录7.1 大模型输出不稳定的排查思路问题表现同样的输入跑两次得到完全不同的候选列表。排查步骤检查temperature参数是否设得过高。如果大于0.5先降到0.3试试。检查提示词中是否有模糊表述。比如“近期表现较好”这种描述模型的理解可能每次都不一样。改成“最近20个交易日涨幅排名前30%”这种量化表述。检查输入数据中是否有缺失值。模型对缺失值的处理方式不确定有时候会忽略有时候会编造。如果以上都没问题尝试增加“输出格式约束”的详细程度。把JSON schema写得更具体减少模型的自由发挥空间。我的经验大模型输出不稳定90%的情况是提示词不够具体。把每个筛选条件都量化成可验证的规则稳定性会大幅提升。7.2 优化算法不收敛的解决方案问题表现scipy.optimize.minimize返回successFalse或者权重结果明显不合理比如某只标的权重为负。排查步骤检查协方差矩阵是否正定。如果标的数量大于样本天数协方差矩阵一定是奇异的。解决方案是减少标的数量或者用收缩估计。检查约束条件是否冲突。比如你要求权重之和为1同时要求每只标的权重不超过0.1但候选标的只有5只那约束就无解了。换初始权重试试。等权不行就换成市值加权或者随机生成多组初始权重取最优。放宽ftol精度要求。有时候收敛失败只是因为精度要求太苛刻。我的经验优化不收敛时先检查数据质量再检查约束条件最后才怀疑算法本身。大部分问题都出在前两步。7.3 数据对齐问题的快速定位问题表现合并多个数据源后出现大量NaN或者日期索引对不上。排查步骤打印每个数据源的日期范围确认是否有重叠区间。检查日期格式是否统一。有的数据源返回2024-01-01有的返回20240101需要先标准化。检查时区设置。如果数据源涉及不同时区需要统一转换到同一时区。用pd.merge的howouter参数做外连接然后检查NaN的分布模式。如果NaN集中在某个日期段说明那个日期段某个数据源缺失。提示数据对齐问题最好在数据层就解决掉不要留到优化层。优化层拿到NaN会直接报错而且错误信息往往不直观。7.4 常见问题速查表问题现象可能原因解决方案模型输出无法解析为JSON提示词未强调“只返回JSON”在提示词末尾加“只返回JSON不要有其他内容”优化权重过度集中协方差矩阵估计误差大使用Ledoit-Wolf收缩估计回测夏普比率远高于实盘过拟合或前视偏差检查数据是否包含未来信息缩短回测窗口数据拉取频繁失败数据源限流增加请求间隔使用本地缓存组合收益率计算出现inf停牌日价格缺失前向填充价格标记停牌日模型调用成本过高提示词过长或调用次数过多压缩输入文本合并批量调用8. 实操心得与避坑指南8.1 提示词迭代的节奏控制提示词不是一次写好的需要反复迭代。但迭代也要讲节奏。我的做法是先用一个粗糙的提示词跑通全流程确认数据流和代码逻辑没问题然后再逐步优化提示词。如果一开始就追求完美提示词很容易陷入“调提示词→发现数据有问题→回去改数据→提示词又不对了”的死循环。每次修改提示词只改一个变量。比如这次只改筛选条件的阈值下次只改输出格式的约束。这样你才能清楚地知道哪个改动带来了什么效果。如果一次改三四个地方效果好了你不知道是哪个改对了效果差了也不知道是哪个改错了。8.2 回测与实盘的差距管理回测夏普比率1.5实盘跑出来0.8这是常态。差距主要来自三个方面交易成本、滑点、以及市场冲击。回测里我通常假设零成本但实盘里买卖都有手续费和印花税频繁调仓的话成本会吃掉很大一部分收益。我的做法是在回测里就加入保守的成本假设每次调仓按0.3%的单边成本计算。这个数字比实际费率略高但能留出安全边际。如果加了成本之后策略还能盈利那实盘大概率也能盈利。如果加了成本就亏了那说明策略的换手率太高需要优化调仓频率。8.3 系统扩展的可行方向这套系统目前是一个基础版本后续可以扩展的方向很多。比如多模型集成不要只用一个模型可以同时调用多个不同的大模型然后对它们的输出做投票或加权平均。不同模型的训练数据和偏好不同集成后能减少单一模型的偏差。动态调仓目前是定期调仓比如每月一次可以改成基于事件触发的动态调仓。比如当某只标的的财务数据出现重大变化时触发重新评估。风险预算除了夏普比率最大化还可以引入风险预算的概念让每个标的对组合风险的贡献度更加均衡。这对降低组合的尾部风险很有帮助。另类数据接入除了财务数据和新闻还可以接入社交媒体情绪、供应链数据、卫星图像数据等另类数据源丰富模型的输入维度。8.4 关于合规与伦理的提醒最后说一个容易被忽视但很重要的问题这套系统是用来辅助研究的不是用来做投资建议的。如果你要把系统输出分享给别人一定要明确说明这是“研究分析结果”不构成投资建议。大模型的输出存在不确定性夏普比率的计算也依赖历史数据过去的表现不代表未来。另外数据的使用要遵守数据源的服务条款。免费数据接口通常有调用频率限制不要恶意刷接口。新闻数据的抓取也要注意版权问题不要大规模复制受版权保护的内容。我个人在实际操作中的体会是这套系统最大的价值不在于它选出了哪几只标的而在于它强迫你把投资逻辑拆解成可验证、可复现的步骤。当你把“我觉得这只股票会涨”转化成“这只股票的营收增速、利润率、新闻情绪得分满足以下条件”时你对投资的理解就已经上了一个台阶。至于最终赚不赚钱那是市场决定的但至少你的决策过程是理性的、可追溯的。
返回列表