Chillarin Trading Lab の仕組み — AI 自動売買の全体像
AI と機械ルール、2 つの戦略を同じ基盤で動かすための部品とデータの流れ
はじめに
Chillarin Trading Lab(以下 CTL)は、米国株を対象にした自動売買システムです。性格の異なる 2 つの戦略を同じ基盤の上で並走させ、どちらがどんな相場で優位になるかを観察できるように作ってあります。
この記事は、CTL が「どんな部品でできていて、どう動いているか」を概観レベルで説明するものです。発注の窓口、売買の判断、データの記録、異常の検知。これらが一本のサイクルとしてどう繋がっているかを、図と表で整理します。
個々のシグナルの定義(何を買い、何で売るか)は別記事に切り出してあります。本記事は「全体の地図」、シグナル記事は「地図の中の一区画の詳細」という役割分担です。具体的な構築手順や設定値の全量は扱いません。そこは別途まとめる予定です。
全体像 — 部品とデータの流れ
CTL は trading-sv01 という小さなサーバ(2vCPU / 4GB の LXC コンテナ)の上で動いています。豪華なマシンではありません。1 日 1 回まわるバッチ的な処理が中心なので、これで足ります。
まず、部品同士がどう繋がっているかを図にします。
(約 500 社)"] SCR["AI スクリーナー
(Claude が 20〜30 銘柄に絞る)"] WL["watchlist
(当日の対象銘柄)"] SRC["市場データ
(OHLCV 取得)"] ML["LightGBM
(ML 自己改善)"] OPEND["moomoo OpenD
(API ゲートウェイ)"] BROKER["moomoo 証券
(発注・約定)"] DB[("TimescaleDB
時系列 DB")] REDIS[("Redis
キャッシュ / dedup")] NOTIFY["LINE 通知"] DASH["Streamlit
ダッシュボード"] MON["Prometheus / Grafana
監視"] ENGINE["売買エンジン
(real / paper-trader)"] FUNDA["Fund A
(AI 判断)"] FUNDB["Fund B
(機械ルール・AI 不使用)"] CLAUDE["Claude
(Anthropic API)"] SP500 ~~~ CLAUDE SP500 --> SCR --> WL --> FUNDA SP500 -- 全銘柄を機械スキャン --> FUNDB FUNDA --> ENGINE FUNDB --> ENGINE SRC --> ENGINE CLAUDE -. 銘柄選定 .-> SCR CLAUDE -. 売買判断 .-> FUNDA ML -. 補助 .-> FUNDA ENGINE --> OPEND --> BROKER BROKER -- 約定結果 --> ENGINE ENGINE --> DB REDIS -. 重複発火防止 .-> ENGINE ENGINE --> NOTIFY DB --> DASH ENGINE --> MON classDef src fill:none,stroke:#5b8ec5,stroke-width:1.5px,color:#e6e6e6 classDef core fill:none,stroke:#e6711d,stroke-width:2px,color:#e6e6e6 classDef engine fill:none,stroke:#e6711d,stroke-width:2.5px,color:#e6e6e6 classDef store fill:none,stroke:#888,stroke-width:1.5px,color:#e6e6e6 classDef out fill:none,stroke:#5b8ec5,stroke-width:1.5px,color:#e6e6e6 class SP500,SRC,WL,SCR src class FUNDA,FUNDB core class ENGINE engine class OPEND,BROKER core class CLAUDE,ML src class DB,REDIS store class NOTIFY,DASH,MON out
中心にいるのは「売買エンジン」です。このエンジンが束ねているのが Fund A(AI)と Fund B(機械ルール)の 2 つの戦略で、それぞれが売買対象の銘柄と市場データを受け取り、自分のロジックで売買を決めます。エンジンはその決定を moomoo OpenD 経由で発注し、結果を記録して通知します。図で見てのとおり、Claude を呼ぶのは Fund A 側だけで、しかも「上流の銘柄選定(AI スクリーナー)」と「Fund A の売買判断」の 2 か所。Fund B はルールだけで完結し、AI を一切使いません(銘柄の選び方も両者で分けています。詳しくは後述します)。この「片方は AI、片方は機械ルール」という対照が CTL の核です。それ以外の部品は、エンジンを支える役割を持っています。
各部品の役割を表で整理します。
| 部品 | 役割 |
|---|---|
| moomoo OpenD | moomoo 証券の API ゲートウェイ。発注・残高照会・建玉照会の窓口になる(米国株 USD 建て) |
| moomoo OpenAPI(SDK) | Python から OpenD 経由で売買するための SDK |
| real-trader / paper-trader | 売買エンジン本体。実弾用とペーパー用の 2 種類を別プロセスで動かす |
| Claude(Anthropic API) | Fund A の AI 判断。銘柄スコアリングと売買判断に、市場のコンテキストを渡して使う |
| LightGBM | ML の自己改善ループ。特徴量生成 → 学習 → 予測でシグナルを補強する |
| TimescaleDB(PostgreSQL 16) | 時系列 DB。価格・建玉・約定・日次集計・判断ログをすべて記録する |
| Redis 7 | キャッシュとサイクルの重複発火防止(dedup) |
| Prometheus / Grafana | メトリクス監視。自宅の監視基盤(chillarin-ops)と連携する |
| FastAPI(Control API) | 緊急停止・全決済・状態取得の制御 API |
| Streamlit | 内部運用画面。2 戦略の状況を並べて見る |
| LINE Messaging API | 売買と異常の通知 |
技術スタックをまとめると、Python 3.12 をベースに、moomoo OpenAPI で発注、判断に Claude(Anthropic API)と LightGBM、記録に TimescaleDB と Redis、起動管理は Docker Compose と systemd、制御と可視化に FastAPI と Streamlit、監視に Prometheus と Grafana、通知に LINE、という構成です。どれも特別なものではなく、自宅サーバで無理なく動く範囲の枯れた部品を選んでいます。なぜこの並びにしたのかという選定の背景は、後ろの「なぜこの構成か」でまとめて触れます。
どう動くか — 1 日 1 回のサイクル
ここは少していねいに書きます。「自動売買」と聞くと、株価を秒単位で監視して値動きに張り付くイメージを持つかもしれませんが、CTL はそうではありません。
プロセス自体は市場が開いている間ずっと常駐していて、内部では 60 秒ごとにループが回っています。ただしそのループが毎回売買するわけではありません。売買の判断(買う/売る)を下すのは、その日 1 回だけに絞ってあります。60 秒ループが実際にやっているのは、市場が今どのフェーズか(プレマーケット/取引時間/時間外)の監視、15 分ごとのニュースチェック、ダッシュボード用の指標更新といった「見張りと記録」で、売買の頻度そのものではありません。
そして判断のもとにするのは、秒単位のティックではなく日足です。Fund A も Fund B も、取引時間に入ってからその日の売買判断を 1 回下し、それで終わり。日中に株価が上下しても、その都度は反応しません。サーバが 2vCPU と小さくても成立するのは、この「判断は 1 日 1 回」という割り切りのおかげです。
1 日 1 回に絞る以上、同じ日に二重に発火すると同じ売買を 2 回出してしまう危険があります。これを防ぐのが Redis です。「今日はもうこの判断を実行した」という印を Redis に置き(重複判定=dedup)、その日すでに走っていれば後続を弾きます。
どの銘柄を対象にするか — 銘柄選定
売買のロジックを説明する前に、「そもそも何を売買対象にするのか」に触れておきます。
Fund A(AI)の出発点は S&P 500 の全構成銘柄(約 500 社)。ここから AI スクリーナー(こちらも Claude を使います)が、出来高の増加・値動きの大きさ・ボラティリティ・直近のモメンタムといった観点で、その日トレードする価値のありそうな 20〜30 銘柄に絞り込みます。絞り込まれた銘柄リスト(watchlist と呼んでいます)は、選定理由つきで記録されます。Fund A はこの watchlist の中から買う銘柄を選びます。
ここで一つ、作りながら気づいて直すことにした点があります。当初は Fund B(機械ルール)も、この AI スクリーナーが選んだ watchlist の中から買う設計にしていました。ですがよく考えると、これはまずい。この実験の目的は「AI と機械ルール、どちらが勝つか」です。なのに Fund B も AI スクリーナーの選んだ候補から買っていたら、Fund B の入口に AI が混ざってしまい、「機械ルールの成績」なのか「AI が良い候補を選んだ成績」なのか分けられなくなります。「機械ルールの戦略」と言いながら、土俵選びは AI に任せている状態でした。
そこで、Fund B は AI スクリーナーを通さず、S&P 500 の全銘柄を機械的にスキャンして買いシグナルが成立した銘柄を直接拾うように変えることにしました。入口から出口まで一切 AI を使わないことで、Fund B は純粋な機械戦略になり、Fund A との比較がきれいになります(この変更は方針を決めた段階で、反映作業はこれからです)。なお Fund B は AI を使わない日足の計算なので、500 社を毎日スキャンしても処理は軽く、全銘柄を見ること自体に技術的な問題はありません。絞っていたのは負荷の都合ではなく、設計の判断だったわけです。
この切り分けには、もう一つ狙いがあります。Fund A は「AI が銘柄を選ぶ(スクリーニング)」と「AI が売買を判断する」の二段構えです。Fund B を AI 抜きの全銘柄スキャンにしておくと、両者の成績差から「AI のスクリーニングそのものにどれだけ価値があったのか」も見えてくる。AI トレードの強みは、売買のタイミング判断より、むしろ銘柄の目利きの方にあるのかもしれない——それを確かめる経路にもなります。
つまり Claude が登場するのは Fund A 側だけ、それも 2 か所です。**銘柄選定(スクリーニング)**と、後述する 売買判断。Fund B は買う・売るのどちらにも AI を使いません。スクリーナーが具体的にどんな基準でスコアを付けているか、その詳細は本記事では扱いません(別途まとめる予定です)。
2 つの戦略の判断
watchlist を受け取った 2 つの戦略は、それぞれ別の仕組みで売買を判断します。
- Fund A(AI): モメンタムの強い銘柄を composite score でランキングし、Claude が市場コンテキストを踏まえて総合判断します。上位 2 銘柄に集中して買い、EMA50 が EMA200 を下抜くデッドクロスで売る。トレンドが続く限り持ち続ける中長期保有型です。
- Fund B(伝統的テクニカルルール): AI を使いません。定番のテクニカル指標 10 種類を機械的に評価し、異なるカテゴリのシグナルが 2 つ同時に成立した銘柄を買います。売りはオニール流の損切り −8% / 利確 +25%。判断はすべてルールで決まります。
各シグナルが具体的に何をどう判定するかは、Chillarin Trading Lab 売買シグナル解説 にまとめてあります。Fund A の中身は AI による銘柄選定と手仕舞い、Fund B の 10 シグナルは 伝統的テクニカルルールによる機械的売買、オニール流の出口は Fund B の出口 −8% / +25% を参照してください。
発注から記録まで
戦略が「買う」あるいは「売る」と決めたあとの流れは、両戦略で共通です。
- moomoo OpenD 経由で発注する
- 約定(FILLED)を確認する
- 約定が確認できてはじめて建玉として計上し、TimescaleDB に記録する
- LINE で通知する
この 2 番目と 3 番目の順序が、地味ですが重要です。発注を出した時点で「買えたつもり」になって建玉を計上してしまうと、実際には約定していない注文を保有中とみなす不整合が起きます。社内ではこれを「ゴースト建玉」と呼んでいて、これが起きると残高計算も売却判断も全部ずれていきます。CTL では約定確認(FILLED ガード)を通った注文だけを建玉に計上することで、この不整合を防いでいます。
記録先の TimescaleDB には、価格(ohlcv_1m)、注文(orders)、建玉(positions)、日次集計(daily_summary)、判断ログ(trade_decisions など)といったテーブルがあります。「いつ・何を・いくらで・なぜ売買したか」を後から全部追えるようにしてあるのがポイントです。自動売買は放っておくと中で何が起きているか分からなくなるので、判断の根拠まで残すようにしています。
リスク管理の仕組み(一定の異常を検知したら売買を止めるサーキットブレーカーなど)も組み込んでありますが、その具体的な閾値は本記事では扱いません。「そういう安全弁が存在する」という事実だけ押さえてください。
なぜこの構成か
ここからは、なぜこういう作りにしたのかという設計判断の話です。仕組みそのものより、こちらのほうが応用が効くかもしれません。
小口で moomoo を選んだ理由
CTL は $3,000 規模の小さな資金を 2 つの戦略に分けて運用しています。この規模で「API で自動売買できて、米国株を USD 建てで扱える」という条件を満たす選択肢として moomoo を選びました。moomoo は OpenD という API ゲートウェイを提供していて、ここを通せば Python から発注できます。他社との細かい比較はここでは踏み込みませんが、「自動化できること」と「USD で米国株を扱えること」が決め手でした。
なお、この moomoo OpenD を Linux 上に自分で構築する手順は、それ自体が一筋縄ではいかない作業でした。そちらは別途、有料記事で詳しく扱う予定です(準備中)。
AI と機械ルールを同じ基盤で並走させる
Fund A(AI)と Fund B(機械ルール)を、わざわざ同じ基盤の上で同時に動かしています。これは比較実験のための対照を作るためです。同じ市場・同じ期間・同じ発注経路という条件を揃えた上で、判断の主体だけを「AI」と「機械ルール」に変える。こうすると、リターンの差が戦略の差なのか環境の差なのかを切り分けやすくなります。基盤を共通化しておくと、片方で見つけた不具合の修正がもう片方にも効くという運用上の利点もあります。
「静かに壊れる」前提で観察を仕込む
CTL を作っていて一番警戒しているのは、エラーで止まることではなく、エラーも出さずに間違ったまま動き続けることです。約定していないのに保有中と思い込む(前述のゴースト建玉がまさにこれです)、通知が来ないまま損失が膨らむ。こうした「静かな故障」は、何も仕込んでいないと気づけません。
CTL で FILLED ガード・LINE 通知・ダッシュボードを揃えているのは、この「静かに壊れる」前提への備えです。FILLED ガードで記録のずれを入口で止め、通知で売買と異常を都度知らせ、ダッシュボードで 2 戦略の状況を一目で見られるようにする。緊急停止や全決済は FastAPI の制御 API から手動でも叩けます。完璧に壊れないシステムを目指すより、壊れたときに気づける経路を用意するほうが現実的だ、という考え方です。
設計の意思決定 — 損切りルールをバックテストで検証した
CTL を動かしていると、「このルール、本当にこの厳しさでいいんだっけ?」という問いが次々に出てきます。その一つが、Fund B(伝統的テクニカルルール戦略・オニール流)の損切り「−8%」と利確「+25%」をどう扱うかでした。前回この記事を書いた時点では「検証中」としていた論点です。その後、自分でバックテストにかけて結論が出たので、何が分かって、何をどう変えたかを記録しておきます。
なぜ「自分のデータで」決めることにしたか
損切り・利確のルールを「どこまで厳密に守るべきか」は、実は投資のプロでも立場が割れます。−8% ルールで知られる William O’Neil の原典は「引けを待つな、ためらわず売れ」という即時執行寄りの書き方をしている一方、後年の実務的な解説には「ザラ場のストップは反転スパイクで叩かれやすいから引けで確認する方がよい」という緩和した立場もあります。同じルール名で中身が割れている。
立場が割れている論点は、人の意見を集めても決着しません。だから自分のバックテストで比べて決めることにしました。ここで一つ大きな落とし穴があります。CTL のバックテストは普段、モメンタム上位の個別銘柄群を対象にしますが、これは「いま強い勝ち組」で構成されているため、過去に遡ると当時存在した退場銘柄(破綻・上場廃止)が最初から除外されます。生存バイアスです。過去が実際よりきれいに見えてしまう。
そこで物差しには、銘柄入れ替わりに左右されない**指数(S&P 500=SPY / NASDAQ-100=QQQ)**を使いました。1999 年からの約 27 年、ドットコム崩壊・リーマン・コロナ・2022 年の 4 つの暴落を含む価格系列に対し、出口ルールだけを差し替えて比較しています。加えて、生存バイアスを承知の上で個別株の対照も 3 社用意しました。**Cisco(CSCO)/ Microsoft(MSFT)/ Apple(AAPL)**です。Cisco は 2000 年 3 月に世界時価総額 1 位、Microsoft は 1999 年末に 1 位、当時の二大巨人でした。Apple は当時瀕死だったのに後に大化けした銘柄。「当時の巨人を当時買っていたらどうなったか」を見るための対照です。
なお、この検証で分かるのは損切り/利確ルール単体の挙動までです。システム全体の損益評価ではありません。指数バックテストは「ルールの性格を調べる実験室」と用途を限定しています。
分かったこと
指数では、機械的な損切りはほとんど報われませんでした。 SPY/QQQ の 27 年で、損切りルールが Buy&Hold に勝っても数 % ポイント差、負ける場面も多い。とくに現状の Fund B と同じ「−8% / +25%」は SPY で +655% と、比較した出口ルールの中で最下位でした。同じ期間の Buy&Hold は +892% です。原因ははっきりしていて、+25% の利確上限が上昇トレンドを何度も早切りし続けたことです。3:1 の利益損失比という設計思想は悪くないのですが、強い指数に当てると利確が足を引っ張りました。
次に、最初の問い「終値かザラ場か」にも答えが出ました。「−8% にザラ場で一瞬触れたら即売る」は、終値で確認してから売るより明確に劣りました。 損切り回数が 1.4〜1.5 倍に増え、損切り直後に買い直してまた損切りする往復ビンタ(whipsaw)も増える。リターンも下がります(SPY: ザラ場 +806% vs 終値 +919%)。「一瞬のヒゲで振り落とされるのはもったいない」という直感が数字で裏付けられた形です。CTL が日足・終値ベースで判定しているのは、結果的に正しい選択でした。
損切りが一番裏目に出たのは、急落してすぐ回復するコロナ型の局面です。QQQ のコロナ局面では Buy&Hold が +11.8% だったのに対し、−8% 終値ルールは −1.6%。損切り後の急反発をノーポジで見送った差がそのまま出ました。また、損切り幅は −8% < −12% < −15% の順で、広げた方が成績が良い場面が多いという傾向もありました。狭い損切りほど無駄に弾かれます。
| 全期間リターン(約 27 年) | −8% 終値(現状) | −12% 終値(注 1) | −15% 終値 | Buy&Hold |
|---|---|---|---|---|
| SPY(S&P 500) | +655.0%(注 2) | +893.9% | +936.8% | +892.0% |
| QQQ(NASDAQ-100) | — | +1601.5% | +1748.1% | — |
| CSCO(Cisco) | +814.0% | +679.3% | +740.0% | +691.0% |
注 1: 損切りのみを差し替えた数字。後述する「損切り −12% / 利確 +30%」の複合ルールの数字ではありません。利確を絡めた複合の検証値は本文の方針記述に留めています。 注 2: SPY の −8% 行だけ利確 +25% を併用した現状ルール(+655%)。他の列は損切り単体の比較で、行ごとに併用条件が違う点に注意してください。
ここで個別株を見ると、指数とは部分的に逆の結果も出ました。Cisco のように「暴落して長く低迷した銘柄」では、損切りが −89% という下落の一部を回避でき、長期で Buy&Hold をわずかに上回ります(CSCO 全期間: −8% 終値 +814% vs Buy&Hold +691%)。一方 Apple のような力強い右肩上がりの銘柄では、損切りはどの幅でも機会損失にしかなりませんでした。切るたびに回復に乗り遅れる。つまり損切りが効くかどうかは「買った銘柄がその後どう動くか」次第で、それは買う前には分からない、というジレンマがあります。
Cisco という生々しい背景
一つ、データの中で目を引いた事実を書いておきます。2000 年に世界時価総額 1 位だった Cisco を 1999 年から 27 年持ち続けても、リターンは +691%(年率およそ 7.8%)。同じ期間の S&P 500(+892%)にすら負けました。途中で −89% の下落を食らい、株価が当時のピークを回復するのに約 25 年かかっています。「当時の最大企業を買って持ち続ける」が、いかに報われなかったか。これは「銘柄を選んで持つ Fund A」と「機械ルールで売買する Fund B」を比べる CTL の実験にとって、生々しい背景になります。
システムへどう反映したか
これらを踏まえ、Fund B の出口を「−8% / +25%」から「損切り −12% / 利確 +30%」に広げることにしました。理由は二つで、狭い −8% は無駄弾きが多かったこと、そして +25% の利確上限が上昇を早切りしていたことです。3:1 の利益損失比とオニール流の「固定 % ルール」という性格は保ったまま、無駄弾きと早切りを減らす方向に調整しました。
ただし正直な留保も書いておきます。バックテストは過去データの机上計算で、将来を保証しません。検証期間は歴史的に強気相場を多く含みます。そして指数で報われなかったからといって個別株でも同じとは限らない、というのは Cisco の例が示すとおりです。だから「−12% / +30% が正解」だとは言いません。今の手元データではこちらの方が筋が良さそうなので、こう変えて運用しながら観察を続ける、という姿勢です。数値の詳しい表は別記事であらためて整理する予定です。
関連記事
CTL に関する記事は役割を分けて書いています。
- シグナルの定義を知りたい場合: Chillarin Trading Lab 売買シグナル解説 に、各シグナルが何をどう判定するか、5 年バックテストが相場環境ごとに何を示したか(バックテストが示したこと)をまとめています。
- 実際に動かし始めた報告: 別記事にまとめています。
- moomoo OpenD の Linux 構築手順: 構築手順は別途、有料記事で詳しく扱う予定です(準備中)。
注記
本記事は CTL という個人実験の記録であり、投資助言ではありません。掲載する仕組みやルールが利益を保証するものでもありません。
戦略の評価に用いるバックテストの数値は、いずれも過去データを使った机上検証です。将来の成績を保証するものではありません。検証期間は歴史的に強気相場を多く含むため、好成績はその前提で読む必要があります。
コメント