前回の記事に引き続き、今回も仮想通貨botの開発状況をまとめていきます。
今回は「Rust×Pythonで行うbot作り」のアイデアをまとめました。
新しいbotの開発ネタとして、記録を残しておきます。
どうせやることだし、先に買っておく。https://t.co/5PhQPzdNVL
— よだか(夜鷹/yodaka) (@yodakablog) February 8, 2025
Rustとは?
Rustは、高速性・安全性・並行性を兼ね備えたシステムプログラミング言語です。Mozillaが開発し、現在はRust財団が管理しています。
Rustの特徴
- メモリ安全性が高い
- 所有権システム(Ownership System) により、ガベージコレクションなしでメモリ管理を行う。
- 借用(Borrowing)とライフタイム(Lifetimes) により、メモリの不正アクセスを防ぐ。
- Nullポインタやデータ競合が発生しにくい 仕組みになっている。
 
- 高速な実行速度
- CやC++と同等のパフォーマンスを発揮。
- ゼロコスト抽象化 により、抽象度の高いコードでもオーバーヘッドがほぼゼロ。
 
- 安全な並行処理
- Fearless Concurrency(恐れない並行処理) を目指し、スレッド競合をコンパイル時に防ぐ。
- std::syncや- tokioなどの強力な並列・非同期処理機能をサポート。
 
- エコシステムが充実
- パッケージマネージャー Cargo により、依存関係管理が簡単。
- 高性能なライブラリ(serdeでシリアライズ、tokioで非同期処理など)。
 
- WebAssembly(Wasm)との親和性
- RustでWebAssemblyを記述し、フロントエンド(Webブラウザ)でも高性能なアプリが動作可能。
 
- C言語との互換性
- FFI(Foreign Function Interface) を利用し、Cライブラリと簡単に連携できる。
 
Rustの用途
- システムプログラミング(OS、組み込みシステム)
- Webバックエンド(Actix、Rocketなどのフレームワーク)
- ブロックチェーン・仮想通貨(Solana、Parity Substrate)
- ゲーム開発(Bevy、Amethyst)
- 分散システム(TiKV、Vector)
- 機械学習(tch-rs、rust-ml)
RustとPythonの組み合わせ
RustはPythonと組み合わせて使うことも可能。たとえば:
- データストリーミングや高速な数値計算をRustで処理し、Pythonで機械学習モデルを実装
- PyO3や- maturinを使って、RustでPythonの拡張モジュールを作成
 
		私の自動取引botでも、Rustでデータストリーミングや価格計算を高速化し、Pythonで取引ロジックを実装するという形が活かせそうです。
📌 PythonとRustの棲み分け
 
		PythonとRustを組み合わせて仮想通貨の自動取引botを作る場合、それぞれの特性を活かして適切な棲み分けをすることが重要です。以下のような役割分担が考えられます。
| 機能 | Rustで実装 | Pythonで実装 | 
|---|---|---|
| データ取得・ストリーミング | 高速なWebSocket処理 ( tokio) | 簡易なAPIアクセス ( requests/websockets) | 
| データ前処理 | 高速フィルタリング・集計 ( polars) | Pandasでデータ解析 | 
| 価格予測 | 数値計算 ( ndarray,nalgebra) | 機械学習 ( scikit-learn,PyTorch) | 
| 取引戦略の実装 | シンプルな戦略のバックテスト ( backtest-rs) | 複雑なMLモデルの適用 | 
| 注文管理・リスク管理 | 低レイテンシな注文処理 ( reqwest,serde) | ロジックの組み合わせ ( ccxt) | 
| ログ管理・監視 | 効率的なロギング ( tracing,log) | 視覚化 ( matplotlib,dash) | 
| バックテスト | 高速なシミュレーション | 柔軟な分析 | 
🌟 各モジュールの具体的な設計
1️⃣ データ取得・ストリーミング
- Rust:
- 高速WebSocket接続(tokio-tungstenite)
- マルチスレッドで並行処理
- serdeを使ったJSONパース
 
- 高速WebSocket接続(
- Python:
- ccxtを使ってスポットデータ取得(低頻度)
- 過去データのロード・解析
 
2️⃣ データ処理・特徴量エンジニアリング
- Rust:
- polarsや- ndarrayを使って超高速データ処理
- 並列処理でリアルタイムフィルタリング
 
- Python:
- pandasでデータ解析
- 時系列データの特徴量エンジニアリング
 
3️⃣ 価格予測
- Rust:
- ndarray,- tch-rs (PyTorch for Rust)を使って数値計算
- 簡単な統計手法(移動平均、ボリンジャーバンド)
 
- Python:
- scikit-learn,- tensorflow,- PyTorchを使って機械学習モデルを構築
- LSTM, Transformer, DQN などを利用
 
4️⃣ 取引戦略
- Rust:
- シンプルなロジック(スプレッドトレード、マーケットメイキング)
- 低レイテンシなアルゴリズム
 
- Python:
- 複雑なアルゴリズム(リスク制御、アービトラージ)
- MLを用いた動的戦略変更
 
5️⃣ 注文処理
- Rust:
- API通信の最適化 (reqwest)
- 非同期注文 (tokio)
- 超低レイテンシな発注
 
- API通信の最適化 (
- Python:
- ccxtでマルチ取引所対応
- デバッグしやすい発注ロジック
 
6️⃣ ログ管理・監視
- Rust:
- tracingを使って軽量ログ記録
- バイナリログフォーマット(パフォーマンス重視)
 
- Python:
- matplotlib,- dashで視覚化
- Slack, Discord, Telegram へのアラート送信
 
🚀 RustとPythonの統合方法
1. PyO3 を使う
RustでPythonのモジュールを作成し、PythonからRustの関数を呼び出す方法。
メリット:Rustの高速性をPythonに統合できる。
例
use pyo3::prelude::*;
#[pyfunction]
fn add(a: i32, b: i32) -> i32 {
    a + b
}
#[pymodule]
fn my_rust_module(py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(add, m)?)?;
    Ok(())
}
Pythonで利用:
import my_rust_module print(my_rust_module.add(3, 4)) # 7
2. FFI (cbindgen) を使う
Rustで共有ライブラリ (.so, .dll) を作成し、Pythonから ctypes や cffi で呼び出す。
メリット:さらに低レベルな最適化が可能。
3. maturin でPythonパッケージを作る
RustをPythonのネイティブ拡張としてビルドし、PyPIパッケージとして配布可能。
📌 まとめ
| 役割 | Rust | Python | 
|---|---|---|
| データ取得 | WebSocketでリアルタイム処理 | API経由でデータ取得 | 
| データ処理 | 高速処理 ( polars) | 柔軟な解析 ( pandas) | 
| 価格予測 | 数値計算 ( ndarray) | MLモデル ( PyTorch) | 
| 戦略実装 | 低レイテンシ戦略 | 高度なロジック | 
| 注文処理 | 高速APIリクエスト ( reqwest) | ccxtを活用 | 
| ログ管理 | tracingで軽量記録 | matplotlibで視覚化 | 
Pythonの強み
- 柔軟な開発
- 豊富な機械学習ライブラリ
Rustの強み
- 高速処理
- 低レイテンシな通信
- 安全な並行処理
→ Rustでリアルタイム処理 & 取引API、PythonでMLとデータ解析 という棲み分けが最適!
 
		この構成で開発を進めると、Pythonの機械学習の柔軟性 と Rustの低レイテンシ高速処理 の両方を活かせます。
実装の例
PythonとRustを組み合わせた仮想通貨自動取引botの設計について、リアルタイムデータ取得(Rust)→ ML戦略処理(Python)→ 取引実行(Rust) という流れで、実際のコード例を交えながら説明します。
🚀 RustでWebSocketデータ取得(リアルタイム)
Rustの tokio を使って、仮想通貨取引所(Bybitなど)からリアルタイムのWebSocketデータを取得します。
📌 Rust(データ取得用)
src/main.rs
use tokio_tungstenite::connect_async;
use tokio::stream::StreamExt;
use serde_json::Value;
#[tokio::main]
async fn main() {
    let url = "wss://stream.bybit.com/realtime";
    let (ws_stream, _) = connect_async(url).await.expect("Failed to connect");
    let (_, mut read) = ws_stream.split();
    println!("Connected to WebSocket!");
    while let Some(msg) = read.next().await {
        if let Ok(msg) = msg {
            let text = msg.to_text().unwrap();
            let json: Value = serde_json::from_str(text).unwrap();
            
            println!("Received: {:?}", json);
        }
    }
}
🔹 Rustのポイント
- tokio_tungsteniteを使って非同期でWebSocket接続
- serde_jsonで受信データをJSONとして解析
- 受信データをリアルタイムで表示(取引所APIによってフォーマットを調整)
📌 Pythonで価格予測モデル
Rustで取得したデータをPythonに渡し、LSTM(長短期記憶ネットワーク)を使った価格予測を行います。
📌 Python(機械学習モデル)
ml_model.py
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
# LSTMモデル定義
class LSTMPredictor(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(LSTMPredictor, self).__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
    def forward(self, x):
        _, (h_n, _) = self.lstm(x)
        out = self.fc(h_n[-1])
        return out
# モデルロード
def load_model():
    model = LSTMPredictor(1, 50, 1)
    model.load_state_dict(torch.load("lstm_model.pth"))
    model.eval()
    return model
# 予測関数
def predict_price(model, data):
    data = torch.tensor(data, dtype=torch.float32).unsqueeze(0).unsqueeze(2)
    with torch.no_grad():
        prediction = model(data).item()
    return prediction
🔹 Pythonのポイント
- PyTorchでLSTMモデルを定義
- 保存済みの学習済みモデルをロード
- WebSocketで受け取った価格データを使って予測
🚀 RustとPythonの連携
Rustで取得したデータをPythonのMLモデルに渡し、予測結果をRustに返します。
これには PyO3 を使用します。
📌 RustからPythonの予測関数を呼び出す
src/lib.rs
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
fn predict_price(price_data: Vec<f32>) -> f32 {
    let gil = Python::acquire_gil();
    let py = gil.python();
    let model_module = PyModule::import(py, "ml_model").expect("Failed to import Python module");
    let model = model_module.call_function0("load_model").expect("Failed to load model");
    let price = price_data.clone().into_py(py);
    let result = model_module.call_function1("predict_price", (model, price))
        .expect("Failed to predict price");
    result.extract::<f32>().unwrap()
}
🔹 RustとPythonの連携のポイント
- PyO3を使ってPythonをRustから呼び出す
- Rustで取得した価格データをPythonのMLモデルに渡す
- Pythonから予測値を取得し、Rust側で処理する
📌 Rustで取引注文の実行
予測結果に基づき、RustでBybit APIを使って取引を行います。
src/trade.rs
use reqwest::Client;
use serde_json::json;
async fn place_order(api_key: &str, secret_key: &str, side: &str, qty: f64, price: f64) -> Result<(), reqwest::Error> {
    let url = "https://api.bybit.com/v2/private/order/create";
    let params = json!({
        "api_key": api_key,
        "side": side,
        "symbol": "BTCUSDT",
        "order_type": "Limit",
        "qty": qty,
        "price": price,
        "time_in_force": "GoodTillCancel"
    });
    let client = Client::new();
    let response = client.post(url)
        .json(¶ms)
        .send()
        .await?;
    println!("Order response: {:?}", response.text().await?);
    Ok(())
}
🔹 Rustの取引処理のポイント
- reqwestを使ってBybit APIにHTTPリクエストを送信
- APIキーとシークレットキー を使って認証
- 予測価格に基づき注文を発注(売買ロジックは後で追加可能)
🔗 RustとPythonの統合フロー
- Rust (tokio) でリアルタイム価格データを取得
- Rust (PyO3) で Python の ML モデル (predict_price) を呼び出し、予測価格を取得
- 予測価格をもとに、Rust (reqwest) で取引注文を実行
- 結果をログに記録し、次の取引機会を待つ
🚀 まとめ
| 機能 | Rust | Python | 
|---|---|---|
| リアルタイムデータ取得 | tokio+serde_json | ccxt(バックアップ用) | 
| データ処理 | polars | pandas | 
| 価格予測 | なし(Rustでも可能) | PyTorchの LSTM モデル | 
| 取引実行 | reqwestでBybit APIへ発注 | なし | 
| ログ管理 | tracing | matplotlibで可視化 | 
 
		この設計で、Rustの超高速処理とPythonの柔軟な機械学習 を最大限に活かすことができます。
しかし、これだけで終わらせるのは面白くないので、もう一工夫してみましょう。
より堅牢なコード
 
		ロジックをさらに改善し、効率的な取引戦略 と パフォーマンスの向上 を図ります。
🛠 改善ポイント
- リアルタイムデータ処理の効率化
- RustでWebSocketを非同期ストリーミング処理
- データのバッファリング で過去データを一定期間保持(時間足データの作成)
- 価格変動率やボラティリティを計算
 
- 価格予測モデルの最適化
- 過去N件の価格をベクトルとして入力し、LSTMで予測
- 価格予測の信頼度スコアを導入し、エントリー判断を最適化
 
- 取引戦略の強化
- 注文執行ロジックを改善(指値注文 + 成行注文の組み合わせ)
- ポジションサイズの動的調整(資金管理)
- 取引履歴を記録し、トレード評価を自動化
 
🚀 改善後のコード
1️⃣ Rustでリアルタイムデータ処理
過去のデータを一定数保持し、価格変動率を計算できるようにします。
📌 Rust(データバッファ付きWebSocket処理)
src/main.rs
use tokio_tungstenite::connect_async;
use tokio::sync::mpsc;
use tokio::task;
use tokio::time::{sleep, Duration};
use serde_json::Value;
use std::collections::VecDeque;
const BUFFER_SIZE: usize = 100; // 過去100件の価格を保持
#[tokio::main]
async fn main() {
    let url = "wss://stream.bybit.com/realtime";
    let (ws_stream, _) = connect_async(url).await.expect("Failed to connect");
    let (_, mut read) = ws_stream.split();
    let mut price_buffer: VecDeque<f64> = VecDeque::with_capacity(BUFFER_SIZE);
    while let Some(msg) = read.next().await {
        if let Ok(msg) = msg {
            let text = msg.to_text().unwrap();
            let json: Value = serde_json::from_str(text).unwrap();
            if let Some(price) = json["price"].as_f64() {
                if price_buffer.len() == BUFFER_SIZE {
                    price_buffer.pop_front(); // 古いデータを削除
                }
                price_buffer.push_back(price);
                // ボラティリティ計算
                if price_buffer.len() > 10 {
                    let volatility = calculate_volatility(&price_buffer);
                    println!("Current Price: {}, Volatility: {:.4}", price, volatility);
                }
            }
        }
    }
}
// ボラティリティ計算(標準偏差)
fn calculate_volatility(data: &VecDeque<f64>) -> f64 {
    let mean = data.iter().sum::<f64>() / data.len() as f64;
    let variance = data.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / data.len() as f64;
    variance.sqrt()
}
🔹 改善点
- 価格データをバッファリング → 過去の価格を保持し、傾向分析可能
- ボラティリティ計算 → 価格の変動率を分析し、リスク評価に利用
2️⃣ Pythonで価格予測(信頼度スコア付き)
予測モデルの信頼度スコアを計算し、取引判断を強化します。
📌 Python(価格予測モデル)
ml_model.py
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
# LSTMモデル定義
class LSTMPredictor(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(LSTMPredictor, self).__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
    def forward(self, x):
        _, (h_n, _) = self.lstm(x)
        out = self.fc(h_n[-1])
        return out
# モデルロード
def load_model():
    model = LSTMPredictor(1, 50, 1)
    model.load_state_dict(torch.load("lstm_model.pth"))
    model.eval()
    return model
# 予測と信頼度スコアの計算
def predict_price(model, data):
    data = torch.tensor(data, dtype=torch.float32).unsqueeze(0).unsqueeze(2)
    with torch.no_grad():
        prediction = model(data).item()
        confidence = np.std(data.numpy())  # 標準偏差を信頼度スコアとして使用
    return prediction, confidence
🔹 改善点
- 信頼度スコア を導入(ボラティリティが高いと信頼度を下げる)
- モデルの柔軟性向上(データを正規化して入力)
3️⃣ Rustで取引注文(動的ポジション管理)
価格変動と信頼度スコアを考慮し、注文量を調整する。
📌 Rust(リスク管理を考慮した発注)
src/trade.rs
use reqwest::Client;
use serde_json::json;
// 注文実行
async fn place_order(api_key: &str, secret_key: &str, side: &str, qty: f64, price: f64, confidence: f64) -> Result<(), reqwest::Error> {
    let url = "https://api.bybit.com/v2/private/order/create";
    // 信頼度スコアに基づいてポジションサイズを調整
    let adjusted_qty = if confidence < 0.01 {
        qty * 0.5 // 信頼度が低い場合はポジションを減らす
    } else {
        qty
    };
    let params = json!({
        "api_key": api_key,
        "side": side,
        "symbol": "BTCUSDT",
        "order_type": "Limit",
        "qty": adjusted_qty,
        "price": price,
        "time_in_force": "GoodTillCancel"
    });
    let client = Client::new();
    let response = client.post(url)
        .json(¶ms)
        .send()
        .await?;
    println!("Order response: {:?}", response.text().await?);
    Ok(())
}
🔹 改善点
- 信頼度スコアに応じて注文量を調整
- リスク管理を強化(不確実な相場では取引量を減らす)
🚀 改善後の全体フロー
- Rust (tokio) でリアルタイムデータ取得(過去データをバッファリング)
- 価格変動率(ボラティリティ)を計算
- Rust (PyO3) で Python の ML モデルを呼び出し、価格予測 + 信頼度スコアを取得
- Rust (reqwest) で APIを呼び出し、信頼度に応じたポジションサイズで注文
- 取引結果を記録し、次の取引戦略にフィードバック
🎯 最適化のメリット
| 改善点 | 効果 | 
|---|---|
| データのバッファリング | 過去の価格変動を分析しやすくなる | 
| ボラティリティ計算 | 相場の安定性を評価可能 | 
| 信頼度スコア導入 | 取引の精度向上 | 
| リスク管理の強化 | 価格変動が大きいときはポジションを減らす | 
 
		この改良で、より堅牢な自動取引ボット になります! 🚀
まとめ
今回、初めてRustを使ったbot開発にチャレンジしてみました。
高速実行が可能なプログラミング言語として採用したRustでしたが、実際に調べて使ってみると、多くの使用方法があることにも気がつきました。
今後の仮想通貨bot開発をより広く展開していくためにも、Rustの習得を進めていきます。
参考にしている本
メインの開発とは別だが、これは今月の宿題。余力があるうちに次のことを進めておく。 pic.twitter.com/JyT01C7n24
— よだか(夜鷹/yodaka) (@yodakablog) February 10, 2025
