先当一回用户:你们卖的是什么
网格 · 合约网格 · DCA / 马丁 · 跟单
四个产品
| 产品 | 核心逻辑 | 要想明白的问题 |
|---|---|---|
| 现货网格 | 在价格区间里等距挂买单和卖单,每次低买高卖赚一格的差价 | 价格涨出或跌出区间怎么办?格子太密,手续费会不会把利润吃光? |
| 合约网格 | 网格加杠杆,分做多、做空、中性三种 | 有杠杆以后,强平价怎么算?(D2 会算) |
| DCA / 马丁 | 越跌越补仓,补仓量按倍数放大,涨到止盈线一起卖出 | 连续下跌时,资金是怎么指数级放大的? |
| 跟单 | 带单员开仓后,跟单者按比例自动复制,带单员从跟单者盈利里分成 | 跟单者余额不够怎么办?滑点由谁承担? |
网格长什么样
price high 30000 ─────────────────── SELL ← 区间上沿 29500 ─────────────────── SELL 29000 ─────────────────── SELL now 28750 ········●·········· 28500 ─────────────────── BUY 28000 ─────────────────── BUY low 27500 ─────────────────── BUY ← 区间下沿 BUY filled @28500 ──► place SELL @29000 (one level up) SELL filled @29000 ──► place BUY @28500 (one level down) profit per round trip = spacing × qty − fee(buy) − fee(sell)
最靠近当前价的那一格空着。每成交一笔,就在相邻格挂一张反向单,所以网格永远是"下面挂买、上面挂卖"。
动画:让网格自己跑
试三件事:① 把格数拉到 20、手续费拉到 0.20%,看每格净利率变成负数;② 切到"单边上涨",看卖单全部成交后手里只剩 USDT(踏空);③ 切到"单边下跌",看买单全部成交后满仓被套。
马丁补仓:钱是怎么放大的
跟单链路
Leader opens LONG 1 BTC (leader equity 10,000 U)
│ event: leader.fill
▼
┌───────────────┐
│ CopyEngine │── load followers(leaderId)
└───────┬───────┘
├──► F1 ratio 0.5x equity 5,000 → 0.25 BTC
├──► F2 fixed 200 U → 0.003 BTC (rounded DOWN to lot)
├──► F3 fixed 50 U → SKIP below minQty
└──► F4 balance too low → SKIP insufficient + notify
编程验证
今日实操(只看不下单,约 30 分钟)
- 找到产品:打开任一大交易所的"交易机器人 / 策略交易 / 策略广场"页面(各家叫法不同),不用注册也大多能看。
- 抄现货网格的参数栏:点"创建现货网格",把每个输入框的名字抄下来:价格区间上下限、网格数量、等差 / 等比、投资额、每格利润率、止盈价、止损价、触发价。每一项旁边写一句"它是什么",对不上就回笔记查。
- 再抄三个:合约网格(多了方向、杠杆、预估强平价)、定投 / 马丁(首单、补仓倍数、价格间隔、最大补仓次数、止盈比例)、跟单(带单员的收益率、最大回撤、跟单人数、分润比例)。
- 算一次:用上面的马丁表,首单 100 U、倍数 2、补 5 次,算出一共要准备多少钱;再看创建页里"投资额"那一栏的最低要求是不是和你算的差不多。
完成标志:一张"四个产品 × 参数"的对照表。D12 会在模拟盘里真的把它们建出来。
自测
网格间距 0.2%,单边手续费 0.1%,这个网格能赚钱吗?
价格一路涨破区间上沿,机器人手里是什么状态?
为什么跟单者的成交价总比带单员差?
打卡
交易的领域模型:订单、精度、永续合约
订单类型 · 状态机 · tickSize / lotSize · 标记价格 · 资金费率 · 强平
订单
- 类型:限价单、市价单、止损单
- 执行约束:
post-only(只挂单,会吃单就拒绝)、IOC(能成交多少算多少,剩下撤掉)、FOK(要么全部成交,要么全部撤掉)、reduce-only(只减仓,不会反向开仓) - clientOid:由你这边生成的订单号,用来查询和防止重复下单,是整个系统幂等的基础
- 订单事件和成交事件的区别:一个订单可能对应多笔成交,仓位和资金要按成交来算
submit ──► OPEN ──fill──► PARTIALLY_FILLED ──fill──► FILLED │ │ cancel cancel ▼ ▼ CANCELED CANCELED (filledQty > 0 !) reject ──► REJECTED (never reached the book) place() timed out ──► state = UNKNOWN → query by clientOid, never assume
"部分成交后撤单"是最容易被漏掉的状态:订单是 CANCELED,但仓位已经变了。
精度:最能看出懂不懂行的地方
raw price 27123.456 tickSize 0.1 BUY → round DOWN → 27123.4 don't overpay SELL → round UP → 27123.5 don't undersell the grid target qty → round DOWN to lotSize never exceed available balance check → price × qty ≥ minNotional, else the exchange rejects it
上面是网格场景下常见的约定,具体方向以你们团队的规范为准。重点是:任何金额和价格都不能用 double 算。
BigDecimal tick = new BigDecimal("0.1");
BigDecimal buy = raw.divide(tick, 0, RoundingMode.DOWN).multiply(tick);
BigDecimal sell = raw.divide(tick, 0, RoundingMode.UP).multiply(tick);
// 注意:new BigDecimal(0.1) 是错的,要用字符串构造
编程验证:先用 double 写,看它怎么挂
永续合约
index price = weighted spot prices from several exchanges
mark price = index + smoothed premium
→ PnL and liquidation use MARK, not last trade
funding (commonly every 8h):
rate > 0 → longs pay shorts (perp above spot, cool the longs)
rate < 0 → shorts pay longs
margin mode:
isolated → only this position's margin is at risk
cross → the whole account backs the position
liquidation → insurance fund → ADL (auto-deleverage) if fund is not enough
强平价计算器(逐仓 · U 本位 · 忽略手续费和阶梯保证金)
推导:保证金 + 浮动盈亏 = 维持保证金时触发强平。做多:entry×q/L + (P−entry)×q = MMR×P×q,解出 P = entry×(1−1/L)/(1−MMR)。先手算 60000、10 倍、0.5%,再用计算器核对。
今日实操(公开接口,不用账号,约 30 分钟)
- 查精度:浏览器打开
https://api.binance.com/api/v3/exchangeInfo?symbol=BTCUSDT,在返回里找PRICE_FILTER的 tickSize、LOT_SIZE的 stepSize、最小下单金额那一项。把这三个数代进上面 roundToStep 编程题的测试里跑一次。 - 查三个价格:打开
https://fapi.binance.com/fapi/v1/premiumIndex?symbol=BTCUSDT,抄下 markPrice(标记价格)、indexPrice(指数价格)、lastFundingRate(资金费率)、nextFundingTime(下次结算时间,毫秒时间戳,换成北京时间)。 - 对界面:打开交易所网页的 BTCUSDT 永续页面,顶部找到同样几个数,确认和接口返回一致,并看看最新价和标记价差多少。
- 算强平价:把当前标记价填进上面的强平价计算器,10 倍做多,抄下"距开仓价"。再改成 20 倍,看强平价离你近了多少。
接口地址以官方文档为准;网络访问遵守所在地和公司的规定,打不开就换其他交易所的公开接口,字段名不同但意思一样。
自测
为什么强平用标记价格,而不用最新成交价?
下单接口超时了,这个订单是什么状态?
一个订单部分成交后被撤销,网格下一步该怎么做?
打卡
行情:盘口是怎么在本地维护的
全量快照 · 增量更新 · 序列号 · 跳号重同步
同步流程
1. open WebSocket, BUFFER deltas seq: 101 102 103 104 ... 2. GET REST snapshot snapshot.seq = 102 3. drop buffered deltas with seq ≤ 102 4. apply 103, 104, ... strictly in order 5. gap? (got 106 right after 104) ──► discard local book, go back to 1 size = 0 in a delta → remove that price level
不同交易所的字段名不同(有的叫 sequence,有的叫 u / U),逻辑都是这一套。去看一家交易所公开 API 文档里"如何正确维护本地订单簿"那一节。
动画:丢一条包试试
先正常丢一次,看它重新拉快照;再勾上"忽略跳号"丢一次,看右下角的不一致档位数,这就是策略拿着错盘口在做决策。
编程验证
今日实操(终端里看真实行情,约 40 分钟)
- 拉快照:
curl 'https://api.binance.com/api/v3/depth?symbol=BTCUSDT&limit=5',看 lastUpdateId(快照的序列号)和前 5 档买卖盘。 - 订阅增量:装一个命令行 WebSocket 客户端(macOS 上
brew install websocat),执行websocat wss://stream.binance.com:9443/ws/btcusdt@depth@100ms。每条消息里的 U 是这批增量的第一个序列号,u 是最后一个。 - 检查连续:抄连续三条消息的 U 和 u,确认"这一条的 U = 上一条的 u + 1"。这就是 D3 的跳号检查。
- 对齐快照:一边开着订阅,一边再拉一次快照,找出第一条满足"U ≤ lastUpdateId + 1 ≤ u"的增量:从它开始应用,前面的丢掉。这就是"先缓冲、再拉快照"。
- 看 K 线:
curl 'https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1h&limit=3',每一行前几个数依次是开盘时间、开、高、低、收、成交量,对照笔记里 K 线那一节。
地址和对齐规则以官方文档为准,各家不同;网络访问遵守所在地和公司的规定。
自测
为什么先连 WebSocket 缓冲,再拉快照,而不是反过来?
发现跳号,能不能只补中间那一条继续用?
本地盘口比真实盘口晚了 500ms,策略会怎样?
打卡
动手写网格机器人(上):跑起来
Java 项目骨架 · 公开行情 · 本地模拟撮合 · 网格状态
整体结构
┌──────────┐ ticks ┌──────────┐ intents ┌──────────────┐
│ MarketWS │ ───────► │ Strategy │ ──────► │ OrderGateway │ ──► PaperMatcher (D4)
└──────────┘ └────▲─────┘ └──────┬───────┘ Exchange API (real job)
│ state │ clientOid
┌────┴──────┐ order/fill │
│ GridState │ ◄─────────────┘
└────┬──────┘
▼
EventLog (append-only) ──► replay on restart (D5)
项目骨架
grid-bot/ ├── market/ PublicWsClient.java // 订阅公开成交流,不需要账户 ├── sim/ PaperMatcher.java // 价格穿过挂单价 → 生成成交事件 ├── core/ GridLevels.java // D1 的 gridLevels │ GridState.java // 每一格:BUY / SELL / EMPTY │ GridStrategy.java // 收到成交 → 算下一张单(下面这道题) ├── order/ OrderIntent.java ClientOid.java ├── log/ EventLog.java // D5 └── copy/ LeaderPublisher.java FollowerConsumer.java // D6
- 行情:任选一家你网络能连上的交易所公开成交流,比如
wss://stream.binance.com:9443/ws/btcusdt@trade,只读、无需账户 - 模拟撮合:只看成交价。买单:成交价 ≤ 挂单价就成交;卖单:成交价 ≥ 挂单价就成交
- 先用单线程事件循环,把所有事件串行处理,别一上来就搞并发
编程验证:策略的核心一步
自测
为什么策略只在订单 FILLED 时挂反向单,部分成交时不挂?
为什么先用单线程事件循环?
打卡
动手写网格机器人(下):重启不乱
事件日志 · 状态回放 · clientOid 幂等 · 与交易所对账
下单超时怎么办
place(clientOid = G7-3-B-12) ──► timeout ?? │ ├─ ✗ retry with a NEW clientOid → may create a duplicate order └─ ✓ query by the SAME clientOid ├─ found → adopt its real state └─ not found → re-place with the SAME clientOid (exchange rejects duplicates → idempotent)
// gridId-level-side-cycle:重启后能从本地状态重新算出来 String clientOid = gridId + "-" + level + "-" + side.charAt(0) + "-" + cycle;
重启对账
local (EventLog replay) exchange (source of truth) ─────────────────────── ───────────────────────── A OPEN ◄──────► A OPEN → keep B OPEN ◄──────► B FILLED → markFilled + next grid step C OPEN ◄──────► (not found) → replace (same clientOid) X OPEN, unknown → cancelOrphan rule: write the event to the log FIRST, then mutate memory
这就是对账。你做过电商对账,这里的思路一样:以外部为准,本地差异逐条归类处理。
编程验证
自测
本地以为 3 个单在挂,交易所说其中 1 个已经成交,怎么处理?
为什么要"先写日志,再改内存"?
交易所上有一张本地不认识的 OPEN 单,为什么要撤?
打卡
接入 Kafka,做一个跟单
分区键 · 顺序 · 热点分区 · 扇出 · 按比例复制
两段式设计
leader.fills ┌───────────────┐ copy.orders ┌──────────────┐
key = leaderId ─────► │ FanoutService │ ─────► key = followerId ─────► │ OrderWorkers │
└───────────────┘ └──────────────┘
ordered per leader explode 1 → N spread evenly,
(hot leader = hot (light work only) ordered per follower
partition)
clientOid = leaderFillId + "-" + followerId → any retry creates the SAME id
producer.send(new ProducerRecord<>("leader.fills", leaderId, fill)); // 第一段
producer.send(new ProducerRecord<>("copy.orders", followerId, order)); // 第二段
本地起 Kafka:docker run -d --name kafka -p 9092:9092 apache/kafka:3.8.0
动画:换一个分区键
编程验证
自测
热门带单员把一个分区打满了,怎么办?
rebalance 会带来什么?
按 symbol 分区有什么问题?
打卡
故障演练:它会在哪里出事
重复消息 · rebalance · 超时 · 断线 · 热点 · 崩溃
六张故障卡:在你自己的项目里逐个制造一遍
重复消息同一条成交事件被消费两次
- 怎么制造
- 处理完不提交 offset,直接重启消费者
- 后果
- 仓位算两遍、跟单下两次
- 防线
- 按 fillId 去重;下单用可推导的 clientOid
rebalance消费者加入或退出
- 怎么制造
- 同一个 group 再启动一个消费者,然后 kill 掉
- 后果
- 重复投递 + 延迟尖刺
- 防线
- 幂等消费;监控 lag;配合 cooperative rebalance 和合理的 max.poll 配置
下单超时不知道到底成功没有
- 怎么制造
- 在 PaperMatcher 里随机让 10% 的下单"成功但不返回"
- 后果
- 用新 clientOid 重试会重复下单
- 防线
- 同一个 clientOid 查询后再决定
行情断线 / 跳号本地盘口不再可信
- 怎么制造
- 断网 10 秒再恢复
- 后果
- 拿旧价格下单、吃单或被拒
- 防线
- 序列号检查、整本重同步、行情延迟超阈值暂停策略
热门带单员一个分区被打满
- 怎么制造
- 让一个带单员挂 1000 个跟单者
- 后果
- 这个带单员的跟单者全部延迟,滑点变大
- 防线
- 两段式扇出;按 followerId 分区;批量下单
进程崩溃写了一半
- 怎么制造
- 在"下单成功"和"写日志"之间 kill -9
- 后果
- 交易所有单,本地不知道
- 防线
- 重启对账:孤儿单按 clientOid 前缀认领或撤销
编程验证:幂等消费
一页总结(自动保存在本机浏览器)
打卡
交易所内部:现货和合约是怎么跑起来的
冻结和解冻 · 撮合引擎 · 价格保护 · U 本位 / 币本位 · 资金费结算 · 强平引擎
后台全景
client ─► gateway ─► order svc ─► pre-trade risk ─► sequencer ─► matching engine │ freeze funds │ trades ▼ ▼ account ◄──────────── clearing ◄────────────── trade events │ market data / push ─► users perp only: index ─► mark price ─► risk engine ─► liquidation engine ─► insurance fund ─► ADL timer (commonly 8h) ─► funding settlement ─► account
gateway 网关 · order svc 下单服务 · pre-trade risk 下单前风控检查 · freeze funds 冻结资金 · sequencer 定序 · matching engine 撮合引擎 · clearing 清算 · account 账户 · trades 成交 · market data / push 行情和推送 · index 指数价 · mark price 标记价 · risk engine 风险引擎 · liquidation engine 强平引擎 · insurance fund 保险基金 · ADL 自动减仓 · funding settlement 资金费结算。现货只走上半张图;合约多出下面两条:一条盯着标记价随时准备强平,一条定时收付资金费。
录屏:一笔现货限价单的一生
怎么玩:滚到这里会自动播放,也可以点"上一步 / 下一步"。盯住上面四个数字和订单簿里被圈出来的单:先冻结 600 U,按时间先吃 A1 再吃 A2,吃到比自己贵的 60010 就停,剩下的挂上去,最后撤单只解冻没成交的那部分。说明了"冻结"是下单时就发生的,成交只是从冻结里扣。
编程验证:价格优先、时间优先
强平引擎沙盘(逐仓 · U 本位 · 做多 1 BTC @ 60,000 · 10 倍)
怎么玩:先慢慢往左拖标记价,看风险率涨到 100% 的那一刻(约 54,271.36,D2 的公式)状态变成"触发强平"。再点"插针到 53,800":强平单成交价比破产价 54,000 还差,亏穿的 200 U 先由保险基金出;基金只有 100 U,剩下 100 U 就要自动减仓。把保险基金改成 500 再看,就不用自动减仓了。设定:保证金 6,000 U,维持保证金率 0.5%(示例值,各家按阶梯不同)。
今日实操(在交易所网站上找真实参数,约 30 分钟)
- 阶梯保证金:找到 BTCUSDT 永续的"杠杆与保证金档位"表(各家叫法不同,常在合约规则或下单面板的杠杆设置里),抄前三档:名义价值区间、最高杠杆、维持保证金率。代进 D8 笔记的阶梯保证金计算器,算 1 BTC、10 倍的强平价,和上面沙盘的 54,271 比一比。
- 保险基金:找到交易所公开的保险基金余额页面,记下 BTCUSDT 这一栏的余额和最近的变化。
- 自动减仓指示:在合约页面的仓位栏找自动减仓排队指示(常见是一排小灯),读一下帮助说明,它排的是什么。
- 手续费等级:找到费率页,抄普通用户的现货和合约挂单 / 吃单费率,按它算一次"600 U 合约仓位开仓挂单、平仓吃单"一共多少手续费。
自测
用户下了一笔限价买单,还没成交,他账户里的"可用余额"变了吗?
撮合引擎为什么普遍做成单线程,而不是多线程并发撮合?
资金费结算任务跑到一半机器重启,重跑一遍会不会把人扣两次?
强平单的成交价比破产价还差,差出来的钱谁出?
打卡
量化交易:五个环节,从数据到实盘
数据 → 回测 → 策略 → 模拟盘 → 实盘 · 双均线 · 海龟交易法则 · 收益 / 回撤 / 夏普 · 资金费率套利
量化系统的五个环节
data ──► backtest ──► strategy ──► paper trading ──► live ▲ │ └──────── live fills and PnL go back to data, re-check ◄─────┘
data 数据 · backtest 回测 · strategy 策略 · paper trading 模拟盘(真行情、假钱)· live 实盘 · live fills and PnL go back to data, re-check 实盘的成交和盈亏回流成新数据,拿来和回测对账。回测排在策略前面,是因为先得有一套能信的回测框架,才能拿它筛策略;否则每个想法都没法判断好坏。
| 环节 | 做什么 | 最容易出的错 | 本站在哪 |
|---|---|---|---|
| 数据 | 实时行情(盘口、成交)+ 历史 K 线(下载、清洗、存储) | 缺 K 线、时间不对齐、只下载了现在还活着的币 | D3 · D9 笔记"数据"节 |
| 回测 | 拿历史数据跑同一份策略代码,算手续费和滑点,出资金曲线和指标 | 未来函数、过拟合、忽略手续费 | D9(下面的回测器、metrics)· D11 TradingView 策略测试器 |
| 策略 | 信号 → 定仓位 → 执行 → 风控 | 只有入场规则,没有仓位和止损规则 | D1 网格 / 马丁 · D9 双均线、海龟、套利、做市 · D11 指标 · D12 手动套路和管仓 |
| 模拟盘 | 真行情、假钱,检验"代码真的按回测那样下单" | 模拟撮合太乐观(挂了就算成交) | D4–D5 本地模拟撮合 · D10 测试网 · D12 模拟盘里建策略产品 |
| 实盘 | 小资金起步、逐步放大、每天对账、一键全撤全平 | 一上来就放大资金;实盘和回测对不上也不查 | D10 · 进组以后 |
策略地图
| 策略 | 靠什么赚钱 | 什么行情会亏 |
|---|---|---|
| 趋势跟踪(双均线、海龟) | 大行情里顺着方向拿住,小亏多次、大赚几次 | 来回震荡,反复开仓又止损(来回打脸) |
| 均值回归(网格属于这类) | 价格来回波动,低买高卖 | 单边行情冲出区间:涨上去踏空,跌下去被套 |
| 做市 | 买一卖一之间的差价,加上挂单返佣 | 单边行情,手里货越积越多;被消息灵通的人吃单 |
| 资金费率套利 | 现货多 + 永续空,涨跌抵消,只收资金费 | 费率转负、两边价差拉大、空单那条腿被强平 |
| 跨交易所搬砖 | 同一个币在两家的价差 | 转账慢、暂停提币、价差在路上反转 |
signal ─► position sizing ─► execution ─► risk check ▲ │ └────────────── fills / PnL feedback ◄─────────┘ backtest: history bars ─► same strategy code ─► simulated matcher (fee, slippage) ─► equity curve ─► metrics
signal 信号 · position sizing 定仓位 · execution 执行下单 · risk check 风控 · fills / PnL feedback 成交和盈亏回流 · backtest 回测 · history bars 历史 K 线 · same strategy code 同一份策略代码 · simulated matcher 模拟撮合 · equity curve 资金曲线 · metrics 指标。回测和实盘最好跑同一份策略代码,只换掉"行情从哪来"和"订单发到哪"。
双均线和海龟:规则一页纸
MA crossover MA(n) = average of the last n closes fast crosses ABOVE slow (golden cross) ─► BUY fast crosses BELOW slow (death cross) ─► SELL / go short signal on close of day t ─► trade on day t+1 (no peeking!) Turtle, system 1 (system 2: 55-day entry, 20-day exit) entry : close breaks the 20-day high ─► BUY 1 unit N : 20-day smoothed true range, N = (19 × N_prev + TR) / 20 unit : equity × 1% / N ─► a 1N move = 1% of equity add : +1 unit every 0.5N in favor, max 4 units stop : 2N below the LAST add, all units move up together exit : close breaks the 10-day low ─► SELL all
MA crossover 双均线 · MA(n) n 日均线 · average of the last n closes 最近 n 天收盘价的平均 · fast / slow 快线 / 慢线 · golden cross 金叉 · death cross 死叉 · go short 做空 · no peeking 不许偷看 · Turtle system 1 海龟系统一 · breaks the 20-day high 突破过去 20 天最高价 · true range 真实波幅 · unit 头寸单位 · add 加仓 · in favor 朝赚钱的方向 · stop 止损 · exit 离场。双均线只回答"什么时候进出";海龟把入场、仓位、加仓、止损、离场全写死了,这才叫"一套能照着执行的规则"。
| 海龟算例:权益 10,000 U · BTC 60,000 · N = 2,400 U | 第 1 单位 | 第 2 单位 | 第 3 单位 | 第 4 单位 |
|---|---|---|---|---|
| 加仓价(每涨 0.5N = 1,200) | 60,000 | 61,200 | 62,400 | 63,600 |
| 加完这一单后,所有单位的止损(最近加仓价 − 2N) | 55,200 | 56,400 | 57,600 | 58,800 |
| 每单位数量 = 10,000 × 1% ÷ 2,400 | 0.041667 BTC(约 2,500 U);4 个单位按各自加仓价算约 10,300 U,差不多 1 倍 | |||
| 满 4 单位时打到 58,800 止损,一共亏 | (1,200 + 2,400 + 3,600 + 4,800) × 0.041667 = 500 U,账户的 5%。只有 1 个单位时止损只亏 200 U(2%) | |||
编程验证:双均线只在"交叉那一天"发信号
编程验证:海龟的加仓和止损计划
策略回测器:网格 · 双均线 · 海龟
怎么玩:上半张是价格(网格画格子;双均线画两条均线,虚线是慢线;海龟画入场通道的上下沿),圆点是买卖点,向上的点是买、向下的点是卖;下半张是资金曲线(粗线是所选策略,细线是开局全买 BTC 拿着不动),灰色阴影是最大回撤那一段。先做对比:同一个行情段,三个策略轮流切一遍。震荡段:网格赚,双均线和海龟反复进出、被来回打脸;单边上涨和单边下跌:反过来,趋势策略赚,网格被甩下或被套。没有哪个策略所有行情都赚,这就是为什么要先判断行情、再选策略。双均线和海龟默认可以做空(合约,1 倍,不算资金费);勾上"只做多"再看单边下跌,趋势策略只能空仓等着。海龟满 4 个单位时大约 2–3 倍杠杆。网格再做三件事:① 三个行情段各看一遍:震荡时网格跑赢,单边上涨时网格早早卖光、明显跑输,单边下跌时跌破下沿后满仓被套。② 格数拉到 120,手续费在 0 和 0.20% 之间来回拖:每格只差 100 U(约 0.17%),一买一卖两次手续费就比它多,0 时还赚,0.20% 时变亏。③ 单边下跌时看最大回撤:网格跌破下沿后就是满仓 BTC,回撤和拿着不动差不多,"网格很稳"只在区间里成立。简化:只用每天收盘价判断有没有穿过格子(一天之内来回穿好几次也只算一次),这正是笔记里讲的"K 线内部不知道先高还是先低"。
资金费率套利计算器
默认值和笔记一致:每 8 小时收一次(常见,各家不同),30 天共 90 次,10,000 × 0.01% × 90 = 90 U;开仓、平仓各两笔,4 × 10,000 × 0.05% = 20 U;净 70 U。占用资金 = 现货 10,000 + 永续保证金 10,000 ÷ 2 = 15,000 U。怎么玩:把费率改成 −0.005 看它怎么变亏;把"平仓时价差盈亏"改成 −80,看一次价差就能吃掉一个月收益;把杠杆调高看占用资金变少,但空单那条腿离强平更近。
编程验证:收益、最大回撤、夏普
今日实操(用真实数据回测,约 40 分钟)
- 下载数据(数据环节):打开
https://data.binance.vision/,进 data → spot → monthly → klines → BTCUSDT → 1d,下载最近 12 个月的 zip,解压出 CSV。没有表头,第 1 列是开盘时间,第 5 列是收盘价。或者直接存接口返回:curl 'https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d&limit=365' -o btc.json。 - 先检查数据:打开一个 CSV 看看有没有缺天、有没有重复(D9 笔记"数据"那节的缺口检查)。
- 导入回测(回测环节):在上面的策略回测器点"导入 CSV / JSON",一次选中全部文件,页面会按时间排序、去重,只在你本机解析,不上传。
- 三种策略各跑一遍(策略环节):网格区间自动取开头价格的 ±10%;双均线试 10/30 和 20/60;海龟试系统一和系统二。每个记下收益、最大回撤、夏普,和"拿着不动"比。
- 写一句结论:这一年是趋势多还是震荡多?哪个策略占便宜?如果换一年呢?(过拟合)
自测
回测里策略每天用"当天收盘价"决定当天开盘就买,收益特别好。问题在哪?
一组参数在去年的数据上收益翻倍,换到今年就亏。最可能是什么问题?
双均线在一段来回震荡的行情里一年亏了不少,每笔都不大。问题出在哪?
海龟规则里,账户 10,000 U,BTC 的 N 从 2,400 变成 1,200,每个单位的数量会怎么变?
两个策略年化都是 30%,一个最大回撤 10%,一个 45%,怎么选?
打卡
实操日:在测试网上真的操作一遍
红线 · 看懂交易界面 · 手动练习 · 故意犯错 · 签名下单 · 实操记录
先记住四条红线
- 内部消息不交易:上币下币、大客户挂单、带单员没公开的持仓、策略参数、风控阈值,不管用谁的账户、在哪家交易所,都不能拿来下单
- 员工交易政策:个人账户要不要报备、哪些品种和时段不能交易,入职第一周主动要来看
- 公司的币:先问清是测试环境还是正式环境、亏赚归谁、能不能转出、品种和杠杆上限;不转出、不和个人账户混用
- 密钥:API Key 只开交易权限,不开提现,绑定 IP;密钥放环境变量,不写进代码,不进 Git
录屏:开一单合约,从头到平仓
怎么玩:每一步会圈出界面上要看的那一块,底下一句话说明在做什么、数字怎么来。建议先让它自动放一遍,再从头一步步点,每一步先自己算数字再看。数字设定:维持保证金率 0.5%、挂单手续费 0.02%、吃单 0.05%,都是示例值,各家不同。到测试网上照这 10 步做一遍,把数字填进下面的实操记录表。
手动练习顺序
| 练什么 | 先自己算 | 在界面上看哪里 | 对应 |
|---|---|---|---|
| 现货:远离市价挂一张限价买单,再撤掉 | 冻结 = 价格 × 数量 | 资产页的可用和冻结 | D8 冻结 |
| 现货:小额市价买 | 成交均价比最新价差多少 | 成交记录里的均价和手续费 | D1 滑点 |
| 合约:逐仓 5 倍开最小多单 | 保证金、强平价 | 仓位栏的强平价 | D2 强平价 |
| 合约:挂着等一次资金费 | 仓位价值 × 费率 | 资金流水 | D2 / D8 资金费 |
| 合约:切双向持仓,同时一多一空 | 两边各自的强平价 | 仓位栏出现两行 | D8 双向持仓 |
| 故意犯错:post-only 挂成吃单、reduce-only 超量、精度不对 | 会被拒还是会成交 | 下单后的报错提示 | 下面的 checkOrder |
签名计算器
怎么玩:打开时算的是公开文档里的例子,签名应该是 c8db5682…bd6b71,右边显示"和文档示例一致"。改任何一个字符(比如把 quantity=1 改成 2),签名整个都变,服务器就能发现参数被改过。点"换成现在的时间戳":服务器会拒绝和它自己时间相差超过 recvWindow 毫秒的请求,防止别人把截获的旧请求再发一遍。签名在你的浏览器里算,密钥不会发出去;但真的密钥也别往任何网页里粘。
编程验证:下单前自己先挡一遍
实操记录表(自动保存在本机浏览器)
先在"自己先算"一栏填你算的数,再去测试网操作,把界面上看到的数填进"界面实际"。两边差不到 0.5% 算对上;对不上就去查是费率、精度还是维持保证金档位不一样,这比对上了学到的更多。
自测
测试网上开了多单,界面上的强平价比你用 D2 公式算的高一点,最可能的原因?
下单接口返回签名错误,但你检查了密钥是对的,下一步先查什么?
同事问"你那个测试单为什么被拒了",像干过的回答是?
打卡
看盘:K 线、画线、指标、合约数据
阳线阴线 · 周期 · 支撑阻力 · 趋势线 · 成交量 · EMA · MACD · RSI · 布林带 · ATR · 持仓量 · 多空比 · 爆仓数据
指标实验台
怎么玩:K 线空心的是阳线(收盘比开盘高),实心的是阴线;右上角是最后一根的读数。这段行情分三段:先上涨,再横盘,最后向下破位。① 勾上 EMA:粗线是 EMA20,虚线是 EMA60。上涨段价格一直在两条线上方;横盘段价格反复穿过 EMA20(十来次),两条线越靠越近、慢慢走平,这时按均线交易就会来回打脸。副图换成 MACD 看同一段,快慢线也交叉了八九次。② 副图选 RSI:上涨段后半程 RSI 连续四十多根待在 70 以上,看到"超买"就去做空会一直亏,这就是 RSI 在强趋势里失灵;破位段它又长时间在 30 以下,"超卖"也不等于该抄底。③ 勾上布林带:横盘段上下轨越收越窄,后面紧跟一次大波动。④ 副图选成交量:破位那十几根的成交量是横盘时的两三倍。⑤ 点"逐根回放",把自己当成站在当时的人:每根新 K 线出来,先判断再看后面。指标只用到当前这根为止的数据,和 TradingView 的算法一致(EMA 用前 n 根的简单平均当起点,RSI 用 Wilder 平滑)。
合约数据四种组合
| 价格 | 持仓量 | 常见解读 | 别忘了 |
|---|---|---|---|
| 涨 | 涨 | 新的多头在进场,上涨有新资金 | 资金费率同时很高时,多头很拥挤,一跌容易连环爆仓 |
| 涨 | 跌 | 空头在平仓(被迫买回)推动上涨 | 平完就没人买了,常常涨不远 |
| 跌 | 涨 | 新的空头在进场 | 资金费率转负且很低时,空头拥挤,可能反抽 |
| 跌 | 跌 | 多头在平仓或被强平 | 爆仓数据里多单爆仓量大时,下跌常常是连环强平造成的 |
这些是参考,不是买卖信号。持仓量、多空比、爆仓数据各家都有公开页面,叫法和统计口径不同(多空比有"人数比"和"大户持仓比"两种,差别很大)。
编程验证:EMA
编程验证:RSI
今日实操(TradingView 或任一交易所的 K 线图,约 60 分钟)
- 打开图:TradingView 搜 BTCUSDT,选一家交易所的永续合约(代码里通常带 .P),周期切到 4 小时。交易所网页的 K 线图也可以,大多就是嵌的 TradingView 图表。
- 多周期:依次切日线、4 小时、15 分钟,各用一句话写"现在是涨、跌还是横盘"。三个周期说法不一致很正常,记下来。
- 加指标:指标里搜 EMA 加两次,长度改成 20 和 60;再加 RSI(14)和布林带(20, 2)。把最后一根的 EMA20、RSI 抄下来。
- 画线:用水平线工具在最近两个明显低点画一条支撑线,用趋势线工具连两个抬高的低点。在支撑线下方设一个价格提醒。
- 看合约数据:在交易所的"合约数据"页(各家叫法不同)找到这个币的持仓量、多空比、资金费率,按上面的四种组合写一句解读。
- 写 Pine 回测(需要免费账号):打开 Pine 编辑器,粘贴下面的双均线策略,加到图上,打开策略测试器看净利润、最大回撤、胜率、交易次数;把手续费改成 0 再看一次。
- 用不了 TradingView:去 D9 回测器点"导入 CSV",用真实日 K 做第 6 步同样的事。
//@version=5
strategy("EMA cross 20/60", overlay=true, initial_capital=10000,
default_qty_type=strategy.percent_of_equity, default_qty_value=100,
commission_type=strategy.commission.percent, commission_value=0.1)
fast = ta.ema(close, input.int(20, "fast"))
slow = ta.ema(close, input.int(60, "slow"))
plot(fast, "fast", linewidth=2)
plot(slow, "slow")
if ta.crossover(fast, slow)
strategy.entry("L", strategy.long) // 金叉:开多
if ta.crossunder(fast, slow)
strategy.close("L") // 死叉:平多
Pine 是 TradingView 的脚本语言。策略默认在信号那根 K 线收盘后、下一根开盘时成交,和 D9 讲的"第 t 天出信号、第 t+1 天成交"是一回事。菜单名、版本号以当时界面为准。
自测
RSI 已经 78 了,是不是该做空?
布林带收得很窄,接下来会往哪边走?
价格在涨,持仓量在跌,资金费率很低。这波上涨像什么?
打卡
交易员的操作手法:从计划到复盘
期望值 · 以损定仓 · 计划委托 · 追踪止损 · OCO · 分批 · 保本止损 · 对冲 · 策略产品亲手建 · 交易日志
交易员的一笔单
plan ─► size by stop ─► conditional order + TP/SL ─► manage (trail, scale out, breakeven) ▲ │ └──────────────── journal + weekly review ◄──────────── exit ◄──────────┘
plan 交易计划 · size by stop 以损定仓:先定止损再算数量 · conditional order 计划委托 · TP/SL 止盈止损 · manage 持仓管理 · trail 追踪止损 · scale out 分批止盈 · breakeven 止损移到保本 · exit 离场 · journal 交易日志 · weekly review 每周复盘。新手的顺序常常是"先下单、再想止损、亏了才复盘",正好反过来。
以损定仓计算器
默认值和笔记一致:10,000 U 账户,这一笔最多亏 1% = 100 U;止损离入场 1,500 U,所以数量 = 100 ÷ 1,500 = 0.0667,向下取整到 0.066 BTC;名义价值 3,960 U,只需要 0.4 倍。怎么玩:把止损改成 59,700(止损更近),数量变大、杠杆变高,但亏损还是 100 U 左右;点"止损 = 入场 − 2 × ATR",用波动来定止损;把止盈改到 61,500,盈亏比降到 1 左右,下面会提示"不值得做"。止损价高于入场价时自动当成做空。
录屏:追踪止损怎么一路跟上去
怎么玩:细线是价格,粗的橙色阶梯线是止损,它只往上走、从不往下。价格每创一个新高,止损就跟到"新高 × 97%";价格回落时止损不动,直到价格碰到它就离场。数字和编程题 trailingStop 的第一个测试一样:最高 63,000 时止损 61,110,价格跌到 60,900 离场,赚 1.5%。对照:如果只用固定止损 58,200,这一笔会一直拿着。
编程验证:以损定仓
编程验证:追踪止损
交易日志(自动保存在本机浏览器)
每笔填:计划风险(U,就是以损定仓时"最多亏多少")、实际盈亏(U)、是否按计划执行、一句话原因。R 倍数 = 实际盈亏 ÷ 计划风险:+2R 就是赚了两倍计划风险。一周以后看平均 R(就是每笔的期望值)和"没按计划"的次数,这比胜率有用得多。
今日实操(模拟盘,约 90 分钟)
- 写计划:挑一个 D11 画过线的位置,按 D12 笔记的模板写:方向和理由、入场、止损、止盈 1 和 2、失效条件。用上面的计算器算数量,盈亏比低于 2 就换一个位置。
- 下计划委托:在模拟盘用"计划委托 / 条件单"(各家叫法不同)挂入场单,填触发价和委托价,同时带上止盈止损。先确认触发价用的是最新价还是标记价。
- 管仓:到第一个止盈先平一半,把剩下一半的止损移到入场价(保本);再给剩下的挂一个回调 3% 的追踪止损。
- 记日志:离场后把这一笔填进上面的日志,截一张图存起来。
- 建现货网格:在模拟交易里手动填参数,不用"AI 推荐":区间用 D11 画的支撑和阻力,格数要满足"每格利润率 > 2 × 手续费率"(按 D1 的网格公式先算),填止损价。
- 建合约网格:选中性或做多,杠杆不超过 3 倍,把界面给出的预估强平价和你用 D2 公式算的对一下。
- 建定投 / 马丁:先用 D1 的马丁表算"最多补几次、一共要准备多少钱",再填首单、补仓倍数、价格间隔、最大补仓次数、止盈比例。
- 跟一次单:挑带单员时看最大回撤、带单天数、平均杠杆、跟单人数,别只看收益率;用小额按固定金额跟。
- 24 小时后:每个产品记 5 个数:成交次数、已实现利润、浮动盈亏、手续费合计、离强平价(或止损价)还有多远。
模拟交易入口和参数名各家不同,以界面为准。入职后用公司的币,也按"先手动、再小额策略"的顺序来,并遵守公司规定(D10 红线)。
自测
胜率 70% 的策略一定赚钱吗?
同样 10,000 U、风险 1%,止损从 1,500 U 收紧到 300 U,数量和杠杆怎么变?亏损呢?
追踪止损回调比例设 0.5%,会怎样?
打卡
进组以后
- 第 1 周:让项目在本地跑起来,拿一个真实订单从头跟到尾,画出全链路
- 重点找三样:订单状态机在哪里、对账或状态恢复在哪里、Kafka 的 topic 和分区键怎么设计
- 翻事故复盘:最快知道这个系统真正在乎什么;看监控大盘:大家平时盯的是哪几个指标
- 第 2 周:认领一个跟稳定性或性能有关的小问题,做出看得见的结果
拿到公司发的币以后
- 先问规矩:是测试环境还是正式环境、能做哪些品种、单笔和总额上限、亏赚怎么算、Key 怎么管、员工交易政策在哪看
- 手动下几单现货:限价、市价、撤单,对着 D8 的冻结规则核对余额,顺手在后台或日志里找到这几笔订单
- 手动开一个最小的 U 本位合约仓位:看标记价、强平价、一次真实的资金费扣款,和 D2 / D10 的记录表对一遍
- 最后才让程序跑:从最小金额的网格开始,先看日志和对账有没有对上,再看赚没赚钱