PyCryptoBot / 策略信号
PyCryptoBot 的买卖信号到底怎么定的:七个方法与一套点数阈值
中文文章讲 PyCryptoBot 策略时,常见说法是「它用了 MACD、RSI、OBV 等多个指标」。这句话不算错,但它把指标个数当成了信号结构,于是读者会以为「加一个指标就多一个信号」。真实结构不是这样:models/Strategy.py 对外只暴露 7 个方法,而默认自定义策略 models/Strategy_CS.py 用的是点数制——把若干条件各自计分,累计分数越过阈值才触发买卖。
这一页把三件事摊开:7 个方法的真实职责、点数阈值在源码里的实际取值(例如默认 pts_to_buy = 9、pts_to_sell = 3,且会随市场趋势分支变化)、以及一个几乎没人提的设计——你自己新建的 models/Strategy_myCS.py 会在导入阶段优先加载,覆盖官方文件,所以升级不会冲掉你的改动。
- PyCryptoBot v8.2.4(main=1fa9aaef,2024-03-04)
- Python 3.11(官方 Dockerfile 基线)
- 交易所范围:Binance / Coinbase / KuCoin
- 验证日期 2026-09-21
- 本站未实机运行机器人
models/Strategy.py 的方法清单与 models/Strategy_CS.py 的 pts_* 阈值整理,非官方结构图)。四格只是入口与计分方式的概括,不是完整调用链;真正的判定顺序以源码为准。七个方法:策略对外只有这些入口
下表是 models/Strategy.py 里定义的实例方法。PyCryptoBot PyCryptoBot 机器人主循环要判断「现在该买、该卖还是该等」,走的就是这几处。把这张表记住,读任何第三方策略教程时都能对上号。
| 方法 | 职责 | 返回 | 典型用途 | 注意点 |
|---|---|---|---|---|
is_buy_signal | 判断当前是否满足买入条件(多组过滤条件全部通过才成立) | 布尔值 | 主循环里决定「这一轮要不要下单买入」 | 它只回答「能不能买」,不负责下单;下单在执行层 |
is_sell_signal | 判断是否满足常规卖出条件(策略层面的卖出意图) | 布尔值 | 持仓状态下评估是否该平仓 | 与 is_sell_trigger 是两个入口,别混用 |
is_sell_trigger | 卖出触发判定,包含止损/止盈一类「不管策略意见如何都要走」的情形 | 布尔值 | 风控优先于策略时使用 | 源码里它是独立方法,说明「信号」与「触发」在设计上就分开 |
is_wait_trigger | 是否进入等待状态 | 布尔值 | 行情不满足任何动作条件时避免乱动 | 「等」是一个明确状态,不等于「没信号就跳过」 |
check_trailing_buy | 移动买入(跟踪下跌后买入)的判定 | 布尔值 | 配合 trailingbuypcnt 使用 | 该开关在标准样本里默认是 0(不生效) |
check_trailing_sell | 移动卖出/移动止损的判定 | 布尔值 | 配合 trailingstoploss 与 trailingstoplosstrigger 使用 | 样本里这两个值分别是 -1.5 与 5,属于「按百分比」的语义,改动前先确认单位 |
get_action | 汇总上述判定,给出「这一步要做什么」的动作结论 | 动作结果 | 主循环的统一出口 | 读日志时看到的动作描述通常来自这里 |
买卖信号到底有几个?
真实的旋钮在 config.json 里:一串 disable* 开关键。下表把它们按「它管的判断方向」列出来,并解释一个反直觉的命名规律。
| 开关 | 它管什么判断 | 值为 1 时发生什么 | 适用场景 | 注意点 |
|---|---|---|---|---|
disablebullonly | 是否要求整体趋势偏多才允许买入 | 取消「只在多头环境买」的限制 | 想扩大买入机会时 | 取消后可能在下跌趋势里也触发买入 |
disablebuynearhigh | 是否禁止在接近阶段高点时买入 | 允许追高买入 | 趋势型行情 | 标准样本里该项默认是 1,也就是默许追高,容易误读 |
disablebuymacd | MACD 相关的买入确认 | 不做 MACD 确认 | 只用其它条件判断时 | 源码注释把 MACD、RSI、OBV 列为「当前买入所依赖」的主要项 |
disablebuyema | EMA 相关的买入确认 | 不做 EMA 确认 | 避免与均线类条件重复计分 | 只出现在 advanced 样本里,标准样本没有这一项 |
disablebuyobv | OBV(能量潮)相关的买入确认 | 不做 OBV 确认 | 成交量数据质量差时 | 标准样本里该项默认是 1 |
disablebuyelderray | Elder Ray 相关的买入确认 | 不做 Elder Ray 确认 | 简化判定链时 | 标准样本里默认是 0,即默认启用 |
disablefailsafefibonaccilow | 斐波那契低点保护(防深跌时买入) | 关闭这层保护 | 需要更激进的入场时 | 标准样本里默认是 1(关闭),属安全相关项 |
disableprofitbankreversal | 止盈回落(保住已有利润)的判定 | 关闭止盈回落保护 | 想让它继续跟随趋势时 | 标准样本里默认是 0(启用),与上一项默认方向相反 |
disable* 的 1 是「关掉这个过滤」,不是「开启」。把 disablebuymacd 设成 1 的意思是不做 MACD 确认,而不是启用 MACD。同一个样本文件里,有的项默认写 0(启用)、有的写 1(关闭),所以「照抄默认值」并不能让你得到一套统一口径——你必须逐项确认它现在到底开还是关。本站依据两份 config 样本的键名与默认值整理,未实机验证每个条件的实际触发频率,也不建议任何参数组合。默认自定义策略怎么判:累计分数比阈值
models/Strategy_CS.py(501 行)是官方提供的默认自定义策略。它的判定思路是把各个条件的判断结果换算成点数,累加后与阈值比较。下面这些数值直接取自源码里的赋值语句。
| 源码里的项 | 实测取值 | 含义 | 注意点 |
|---|---|---|---|
self.pts_to_buy | 9(默认分支) | 累计买入分数达到 9 才允许买入 | 源码注释原文是「more points requires more signals to activate, less risk」——分数门槛越高,需要越多的条件同时成立 |
self.pts_to_sell | 3(默认分支) | 累计卖出分数达到 3 就触发卖出 | 注释原文是「requiring fewer pts results in quicker sell signal」——卖出门槛刻意设得比买入低 |
self.pts_sig_required_buy | 0 | 买入额外要求的「必备信号个数」 | 源码注释说明:要给某个信号加「必备」约束,就在对应段落里写 self.pts_sig_required_buy += 1 |
self.pts_sig_required_sell | 0 | 卖出额外要求的必备信号个数 | 注释写明卖出侧「currently 0」,并给了同样的累加写法 |
趋势分支:Low risk, buy! buy! buy! | pts_to_buy = 8 / pts_to_sell = 5 | 判定为低风险时放宽买入、收紧卖出 | 阈值是成对变化的,不是单独调一个 |
趋势分支:Less risk, buy medium points | pts_to_buy = 9 / pts_to_sell = 4 | 风险略高时提高买入门槛 | 默认值对应的就是这个分支 |
趋势分支:High risk, no buying, Sell NOW! | pts_to_buy = 100 / pts_to_sell = 3 | 用 100 把买入门槛抬到实际上不可能达到 | 「禁止买入」是靠抬高阈值实现的,不是靠一个布尔开关——读代码时才看得出来 |
趋势分支:Risky, don't buy yet / Too risky, don't buy yet | 两者同样是 pts_to_buy = 100 | 同样以高阈值实现「暂不买入」 | 源码里被注释掉的 10 说明这些值是人为选定的,不是推导出来的 |
| 趋势判定输入 | 由 SMA10/SMA50 与 SMA50/SMA100 两组均线关系计算 | 得到 self.market_trend 文本 | 也就是说「市场趋势」这一步本身也是均线判断,不是外部数据 |
路径一:直接用官方 Strategy_CS
仓库自带、随主分支更新,别人踩过的坑有迹可循。代价是它内置的一套阈值(8/9/100、3/4/5)是作者按自己的判断选定的,你的币对与周期未必适用,而且你的调整意愿无法体现在文件里——下一次 git pull 会覆盖它。
路径二:自己建 Strategy_myCS.py
把官方文件另存成 models/Strategy_myCS.py 再改。导入阶段会优先加载它,所以你的修改在升级后仍然生效。代价是这份文件从此归你维护,官方后续对策略的改动不会自动进到你的版本里,两边的思路会逐渐分叉。
路径三:关掉自定义策略
不启用自定义策略时,判定走 models/Strategy.py 里的常规信号逻辑,配置侧的 disable* 开关才有意义。两种模式下的可调项是不一样的——先确认 enable_custom_strategy 当前取值,再去改别的开关,否则你会改了不该改的东西。
Strategy_myCS.py 是什么?为什么仓库里没有它
这是本站认为最值得单独讲一句的设计。它不写在 README 的显眼位置,但决定了「你能不能在升级后保住自己的策略改动」。
确认官方文件长什么样
命令:
ls models/Strategy_CS.py,或直接打开看它的方法列表(tradeSignals、buySignal、sellSignal等)。说明:先把要改的基线看清楚,避免把自己的理解当成官方实现。预期:能看到阈值赋值语句(如self.pts_to_buy = 9)与你打算改的段落。另存为 myCS,而不是直接改官方文件
命令:
cp models/Strategy_CS.py models/Strategy_myCS.py。说明:Strategy.py在导入时会先尝试from models.Strategy_myCS import Strategy_CS as myCS,成功就用你的版本,失败才回落到官方Strategy_CS。预期:仓库里出现一个新的models/Strategy_myCS.py。只改你自己那份
命令:在你新建的文件里修改阈值或加信号计数。说明:官方文件保持原样,这样即使以后合并冲突也集中在你的文件里。预期:改动后仍能通过导入(语法错误会导致回落到官方版本,表现出来是「我的改动没生效」而不是报错)。
用日志验证到底加载了哪一份
命令:以非 live 模式启动一轮,观察日志中的策略相关输出。说明:加载回落是静默发生的,必须主动确认。预期:能看到你的改动带来的行为差异;如果没有任何变化,优先怀疑是 import 失败触发了回落。
| 你可能会改什么 | 应该放在哪里 | 升级(git pull)时会不会丢 | 注意点 |
|---|---|---|---|
买卖阈值(pts_to_buy / pts_to_sell) | models/Strategy_myCS.py | 不会丢(优先加载用户文件) | 注意阈值是成对变化的,只改一个可能让买卖不对称 |
| 趋势分支的判定文本与阈值 | models/Strategy_myCS.py | 不会丢 | 趋势由 SMA10/50 与 SMA50/100 计算,改分支前先确认均线周期是否匹配你的 K 线周期 |
| 新增一个「必备信号」约束 | models/Strategy_myCS.py | 不会丢 | 按源码注释在对应段落写 self.pts_sig_required_buy += 1,漏写等于没加 |
| 自定义技术指标实现 | models/Trading_myPta.py(CHANGELOG 6.4.0 记录的同类机制) | 不会丢(同类覆盖设计) | 与策略文件是两条并行机制,别把指标代码塞进策略文件 |
直接改官方 Strategy_CS.py | 官方文件本身 | 会被覆盖 | 这是最容易犯的错:本地跑得好好的,一次升级就回到原样 |
只调 config.json 的 disable* 开关 | config.json | 不会丢(配置文件不在版本控制里) | 但只在未启用自定义策略时才是主要手段,两套机制的作用点不同 |
models/Strategy_myCS.py 在仓库里并不存在(直接请求该路径返回 404)。也就是说这个「用户覆盖位」是留给使用者新建的,不是一个已经放好的示例文件。你不需要去找它的示例——把官方那份复制过去就是起点。写自定义策略前要接受哪七条约束?
下面每一条都能在仓库里找到对应依据。它们的共同作用是:让你在「策略不按预期工作」时,能分清是策略写法问题,还是框架本身的边界。
| 边界 | 说明 | 你可能踩的坑 | 可以先做的检查 |
|---|---|---|---|
| 仓库内没有滑点参数 | 配置样本里找不到以滑点命名的开关 | 以为模拟结果已经包含滑点,于是高估了净收益 | 把自己的滑点假设写进研究记录,别指望框架替你扣 |
| K 线周期只有 7 档 | Granularity 枚举固定为 1m/5m/15m/30m/1h/6h/1d | 想用 4 小时或 2 天周期,发现配置里没有对应值 | 先确认你的策略在 7 档里能否表达,再考虑改代码 |
| 历史 K 线根数受交易所限制 | CHANGELOG 记录过某交易所只返回 100 行、需要传起始日期补足的情况 | 指标预热不足,导致开头一段时间没有信号 | 核对每次取到的行数是否够你的最长均线周期 |
指标库来自 pandas-ta | requirements.txt 未钉版本,属漂移项 | 换了环境后指标数值与之前不一致,难复现 | 把实际安装到的版本记录下来 |
| talib 是可选项 | 不在任何 requirements 文件里,装了会自动加载 | 以为默认走 talib,实际用的是 pandas-ta | 确认环境里是否真的安装了 |
enable_pandas_ta 也是开关 | advanced 样本里显式写了这一项 | 只改了策略文件却忘了看这个开关的状态 | 先确认判定链走的是哪套指标实现 |
| 自定义策略不在官方测试覆盖内 | 仓库的单元测试针对官方实现 | 升级后行为变化却查不到原因 | 自己给关键阈值写一份可回归的检查 |
8/9/100、3/4/5)是源码里的赋值,它们的实际效果取决于你的币对、周期与市场阶段,不能据此判断策略优劣。任何自定义策略上线前都应当经过模拟运行与样本外检验。关于策略与信号的高频问题
回答依据 models/Strategy.py、models/Strategy_CS.py 与两份 config 样本的实测内容;本站未实机运行PyCryptoBot PyCryptoBot 机器人,涉及实际效果的部分一律不予断言。
PyCryptoBot 的买卖信号到底有几个?
取决于你问的是哪一层。在 models/Strategy.py 这一层,对外是 7 个方法:is_buy_signal、is_sell_signal、is_sell_trigger、is_wait_trigger、check_trailing_buy、check_trailing_sell、get_action。在默认自定义策略 Strategy_CS 这一层,判定是「多个条件各自计分、累计分数比阈值」,阈值本身就是一组(如默认 pts_to_buy = 9、pts_to_sell = 3)。所以「信号个数」这个问法在两种模式下答案不同,以源码实现为准。
能不能完全不改代码,只靠改 config.json 调策略?
能,但只在未启用自定义策略的模式下,配置里的 disable* 开关才是主要调节手段。如果启用了自定义策略,判定逻辑由策略文件决定,配置开关的作用范围会变小。建议先确认 enable_custom_strategy 的当前取值,再决定去改哪里——顺序反了会出现「改了配置但行为没变」的困惑。
disable* 开关设成 1 是开启还是关闭?
是关闭那个过滤条件。例如 disablebuymacd = 1 表示不做 MACD 确认。这个命名方向与直觉相反,而且两份样本里各开关的默认值并不统一(有的 0、有的 1),所以「照抄样本默认值」并不等于得到一套统一口径,必须逐项确认。
我改的 Strategy_myCS.py 会不会被升级覆盖?
不会——这正是这个设计的用途。导入时先尝试加载 models.Strategy_myCS,成功则优先使用;失败才回落到官方 models/Strategy_CS。要提醒的是回落是静默的:如果你的文件有语法错误,程序不会报「myCS 加载失败」,而是直接走官方逻辑,表现出来是「我的改动没生效」。所以要主动看日志确认。
自定义策略需要写单元测试吗?
官方单元测试覆盖的是官方实现,你的自定义文件不在其中。这不是「必须写测试」的规定,而是一个事实:升级后你的策略行为变化时,没有任何自动机制会告诉你。可行做法是为你依赖的关键阈值写一份最小可回归的检查(例如给定一段固定输入,确认算出的分数与判定结果符合预期),成本不高但能定位回归。
talib 和 pandas-ta 该怎么选?
本站不给推荐。可核对的事实是:requirements.txt 里有 pandas-ta(未钉版本),talib 不在任何 requirements 文件里、属于可选依赖、装了会自动加载;此外 advanced 样本里有一个 enable_pandas_ta 开关。也就是说「用哪套指标实现」受包安装状态与配置开关共同影响。选择时应先确认你的环境实际加载了哪一个,再去看对应的指标数值。
本站对策略逻辑验证到什么程度?
只做了代码层核对:列出方法清单、抄录阈值赋值语句、确认两份 config 样本的键名与默认值、确认 Strategy_myCS.py 在仓库中不存在。本站没有运行PyCryptoBot PyCryptoBot 机器人、没有连接任何交易所账户、没有下单,因此不提供任何关于阈值好坏、信号频率或实际表现的结论。任何策略上线前请自行完成模拟运行与样本外检验。