Skip to content

Bitbank#312

Merged
yasstake merged 15 commits into
mainfrom
bitbank
Sep 1, 2025
Merged

Bitbank#312
yasstake merged 15 commits into
mainfrom
bitbank

Conversation

@yasstake

Copy link
Copy Markdown
Owner

Add public ws message parser

@coderabbitai

coderabbitai Bot commented May 26, 2025

Copy link
Copy Markdown
📝 Walkthrough

"""

Walkthrough

この変更セットは、Bitbank取引所のサポートを大幅に追加し、RESTおよびWebSocketクライアントの実装、関連データ構造、シリアライズ・デシリアライズ処理、テスト、ならびにPythonバインディングへの公開を行っています。また、環境変数や設定ファイルの取り扱い改善、既存取引所のAPIやテストの整理・拡張も含まれます。加えて、JupyterノートブックやPythonスクリプトによるBitbankのバックテスト・フォワードテスト例も新規追加されています。

Changes

ファイル/グループ 変更概要
exchanges/bitbank/src/market.rs, message.rs, rest.rs, ws.rs, socket.rs, config.rs, lib.rs Bitbank取引所の市場クラス、REST・WebSocketクライアント、メッセージ構造体、シリアライズ処理、設定、テスト、Pythonバインディングを新規実装。
modules/rbot_lib/src/common/env.rs, bar.rs, order.rs, config.rs, ccxt_config.rs 環境変数の大文字化・ロギング改善、Pythonバインディング用属性追加、マーケット設定取得APIの拡張。
modules/rbot_lib/src/db/archive.rs, df.rs 不要なインポート・関数の削除、CSV→Parquet変換責務の整理。
modules/rbot_lib/src/net/ws.rs WebSocketクライアントにsocket.io対応フラグ追加、初期メッセージ処理の分岐を導入。
exchanges/binance/src/config.rs, rest.rs, ws.rs 未使用インポート削除、WebSocketテスト追加、archive系関数の削除。
exchanges/bybit/src/config.rs, market.rs, rest.rs, ws.rs インポート整理、注文APIにclient_order_id追加、WebSocketクライアント初期化パラメータ追加。
exchanges/bitflyer/src/market.rs open_marketの引数をMarketConfigからシンボル文字列へ変更。
modules/rbot_market/src/market.rs kline→trade変換時に期間フィルタを追加。
modules/rbot_session/src/runner.rs, session.rs Pythonバインディング属性追加、エラー処理・セッション管理のリファクタ。
src/lib.rs BitbankクラスをPythonバインディングに追加。
doc/environment.md 取引所アクセスキーの環境ファイル設定方法を新規ドキュメント化。
python/rbot/__init__.py タイプチェック抑制コメント追加、著作権年更新。
test/00_suite/10_ccxt/test_ccxt_config_generate.py, test_00exchange.py, test_01market_basic.py Bitbank対応のテスト追加、設定指定方法の文字列化などテストケース拡張。
test/bitbank_test/basilbot_backtest.ipynb, download.py, nullagent.py, test_market_basic.py Bitbank用のバックテスト・フォワードテストノートブック、ダウンロード・エージェント実行スクリプト、マーケット基本テストを新規追加。

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Bitbank
    participant BitbankMarket
    participant BitbankRestApi
    participant BitbankPublicWsClient

    User->>Bitbank: new()
    User->>Bitbank: open_market("BTC/JPY")
    Bitbank->>BitbankMarket: async_new(...)
    BitbankMarket->>BitbankRestApi: DB/OrderBook初期化
    User->>BitbankMarket: download(...)
    BitbankMarket->>BitbankRestApi: get_board_snapshot()/get_recent_trades()
    User->>BitbankMarket: open_market_stream()
    BitbankMarket->>BitbankPublicWsClient: open_stream()
    BitbankPublicWsClient-->>BitbankMarket: 市場データ配信
    BitbankMarket-->>User: データ/イベント通知
Loading

Possibly related PRs

Poem

うさぎの耳でピョンと聞く、
Bitbankの波がやってきた!
RESTもWebSocketも、データがいっぱい、
市場も注文も、うさぎは大忙し。
テストにノートに、跳ねるよロジック、
新しい冒険、みんなでGo!
 ∩_∩
(・x・)ノ =🐇=
"""

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch bitbank

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🔭 Outside diff range comments (1)
exchanges/bitbank/src/rest.rs (1)

237-268: ⚠️ Potential issue

logdf_to_archivedfメソッドが未実装です。

このメソッドはtodo!()を返しており、呼び出されるとパニックが発生します。

🧹 Nitpick comments (19)
test/bitbank_test/download.py (1)

3-3: 未使用のimportを削除してください

静的解析ツールが指摘している通り、init_loginit_debug_logがimportされていますが使用されていません。

以下の修正を適用してください:

-from rbot import init_log, init_debug_log

もしくは、コメントアウトされているデバッグログ初期化を有効にする予定がある場合は、そのままでも構いません。

🧰 Tools
🪛 Ruff (0.11.9)

3-3: rbot.init_log imported but unused

Remove unused import

(F401)


3-3: rbot.init_debug_log imported but unused

Remove unused import

(F401)

doc/environment.md (2)

7-12: コードブロックに言語指定を追加してください。

マークダウンのベストプラクティスに従い、コードブロックには言語を指定することを推奨します。

-```
+```text
 .env/rusty-bot/
 └── BITBANK.env
     BINANCE.env
     BINANCE_TEST.env

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

7-7: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

---

`19-22`: **ファイル名のテンプレート表記を明確にすることを検討してください。**

コードブロック内で`{取引所名.env}`というテンプレート表記が使われていますが、実際のファイル名の例を示すか、より明確な表記にすることで理解しやすくなります。

例えば以下のような表記を検討してください:
```diff
-```{取引所名.env}
+```bash
+# ファイル名: BITBANK.env
 API_KEY=取引所から提供されるAPIキー
 API_SECRET=取引所から提供されるAPIシークレット

</blockquote></details>
<details>
<summary>exchanges/binance/src/ws.rs (2)</summary><blockquote>

`90-91`: **ブール値の意図を明示してください**  
`false` をそのまま位置引数で渡すと可読性が低く、後から見た際に何のフラグか判断しづらくなります。  
`socket_io_client: false` の意味が伝わるよう、  
* ビルダー/構造体初期化式で名前付き引数にする  
* もしくは `const USE_SOCKET_IO: bool = false;` を用いる  
などの方法で自己説明的にすることを推奨します。  



Also applies to: 191-192

---

`167-168`: **未使用フィールドはプレフィックスで回避を**  
`#[allow(dead_code)]` で抑制するより、構造体フィールド名を `_server` としておく方が明確で安全です。

</blockquote></details>
<details>
<summary>modules/rbot_session/src/runner.rs (1)</summary><blockquote>

`926-931`: **借用は問題ありませんが変数は未使用です**  
`let session = py_session.borrow_mut(py);` を取得後すぐ `agent.call_method1` に渡すのみで、以後 `session` を利用していません。  
以下のようにワンライナーで渡すとスコープが短くなり安全です。  
```diff
-agent.call_method1("on_init", (session,))?;
+agent.call_method1("on_init", (py_session.borrow_mut(py),))?;
exchanges/bitbank/src/socket.rs (2)

26-37: 同期テストはブロッキングになります
標準スレッド + sleep() による待機はテスト時間を延ばし CI を不安定にします。
tokio::testtokio::time::sleep を用いた非同期実装へ変更し、
タイムアウトを短く設定することを推奨します。


41-46: コメントと購読チャンネルが不一致です
コメントでは BTC/JPY trades とありますが、実際には "depth_diff_xrp_jpy" を購読しています。
誤解を避けるためコメントか引数を一致させてください。

test/bitbank_test/nullagent.py (2)

2-2: 未使用のインポートを削除してください。

静的解析で検出された未使用のインポートを削除する必要があります。

以下の差分を適用して未使用のインポートを削除してください:

-from rbot import Session
 from rbot import Runner

 from rbot import Bitbank

-from rbot import init_debug_log
 from rbot import init_log
-from rbot import OrderSide
 from rbot import time_string
-from rbot import NOW, DAYS

Also applies to: 7-7, 9-9, 11-11

🧰 Tools
🪛 Ruff (0.11.9)

2-2: rbot.Session imported but unused

Remove unused import: rbot.Session

(F401)


52-60: コメントアウトされたコードを削除してください。

使用されていないコメントアウトされたコードは、可読性を低下させます。必要に応じてバージョン管理システムから復元できます。

コメントアウトされたコードブロックを削除することを推奨します。

exchanges/bybit/src/ws.rs (1)

99-99: 新しいパラメータの目的を明確にしてください

AutoConnectClient::newに追加されたfalseパラメータの目的が不明確です。このパラメータが何を制御するのか、コメントまたはドキュメントで説明を追加することをお勧めします。

また、このPRの目的は「Bitbank public wsメッセージパーサーの追加」ですが、Bybitのファイルを変更する理由を説明してください。

modules/rbot_lib/src/db/archive.rs (1)

568-638: コメントアウトされたコードを削除してください

行606-637にコメントアウトされた古い実装が残っています。これらのコードは混乱を招く可能性があるため、削除することをお勧めします。

CSVからParquetへの変換処理をAPIレイヤーに移動したことは、責任の分離の観点から良い設計変更です。

modules/rbot_lib/src/common/env.rs (1)

55-73: ログレベルの見直しを検討してください

環境変数ファイルが見つからない場合(行55)はwarnレベルですが、キーが見つからない場合(行72)はerrorレベルになっています。

一貫性の観点から、両方ともwarnレベルにするか、重要度に応じて適切に設定することをお勧めします。

-        log::error!("key [{}] is not found", key);
+        log::warn!("key [{}] is not found in env file", key);
modules/rbot_lib/src/common/bar.rs (2)

53-58: CString の生成場所と無駄なコピーを整理しましょう

CString::new を GIL 外で呼び、その後 as_c_str() をクロージャ内で参照しています。
この方式は動作しますが、毎回ヒープを確保する上に3メソッドで重複しています。

  • py_script.as_bytes() を直接渡せば CString 不要
  • 共通処理をヘルパー関数に抽出すると可読性と保守性が向上します。

148-152: コード重複の解消を検討してください

PyFileBar::init でも同様の CString 生成/from_code 呼び出しが繰り返されています。
共通ユーティリティにまとめることでバグ混入を防ぎ、今回のような不一致(PyRunningBar の型間違い)も防げます。

modules/rbot_lib/src/common/ccxt_config.rs (1)

150-175: データ正規化の重複を回避するヘルパーの導入を提案

get_market_config_by_native_symbolget_market_config
同一の FeeType 判定・MarketConfig::new 呼び出しが重複しています。
共通関数に切り出すことで将来的なパラメータ追加時の修正漏れを防げます。

test/bitbank_test/basilbot_backtest.ipynb (3)

134-179: BasilAgentクラスの実装について改善提案があります

実装は論理的に正しいですが、以下の改善を推奨します:

  1. ポジション判定のマジックナンバー(0.001)はORDER_SIZEの一部として定義すべきです
  2. print文はログ出力に置き換えることを推奨します
 class BasilAgent:
     def __init__(self):
         self.OFFSET = 0.00_05
         self.EXPIRE_TIME = 600    # 600[sec] = 10[min]
         self.ORDER_SIZE = 0.01
         self.RANGE = 300
+        self.MIN_POSITION_THRESHOLD = self.ORDER_SIZE / 10  # 最小ポジション閾値

     # ... 省略 ...

-        if session.position <= 0.001:    # ポジションが少ない場合は買い注文を出す。
+        if session.position <= self.MIN_POSITION_THRESHOLD:    # ポジションが少ない場合は買い注文を出す。
             order_price = ohlcv['close'][-1] * (1 - self.OFFSET)
-            print("BUY ORDER: ", order_price, self.ORDER_SIZE)
+            session.log_info(f"BUY ORDER: price={order_price}, size={self.ORDER_SIZE - session.position}")
             session.limit_order('Buy', order_price, self.ORDER_SIZE - session.position)

         else:                       # ポジションがある場合は売り注文を出す。
             order_price = ohlcv['close'][-1] * (1 + self.OFFSET)
-            print("SELL ORDER: ", order_price, session.position)
+            session.log_info(f"SELL ORDER: price={order_price}, size={session.position}")
             session.limit_order('Sell', order_price, session.position)

188-206: MyAgentクラスのクリーンアップが必要です

未使用の変数とコメントアウトされたコードを整理することを推奨します。

-MARGIN = 0.05

 class MyAgent:
     def __init__(self):
         self.last_update = 0
         self.order_size = 0.001

     def on_clock(self, session, clock):
         pass

     def on_tick(self, session, side, price, size):
         pass
     
-#    def on_update(self, session, updated_order):
-#        print("on_update", updated_order)
     def on_account_update(self, session, account):
         print("account update: ", session.current_time, account)

528-568: 可視化コードの重複を削減することを推奨します

バックテストとフォワードテストで同じ可視化コードが重複しています。共通関数として抽出することを推奨します。

以下のような共通関数を作成することを提案します:

def create_trading_visualization(orders, ohlcv, log, title="Trading Result"):
    """トレード結果の可視化を行う共通関数"""
    import plotly.graph_objects as go
    from plotly.subplots import make_subplots
    
    fig = make_subplots(rows=4, cols=1, shared_xaxes=True, vertical_spacing=0.1, 
                        row_heights=[0.1, 0.1, 0.1, 0.6],
                        subplot_titles=("range", "psudo-position", "psudo-profit", "candlestick"))
    
    # 共通の可視化ロジック
    # ... (既存のコードを関数化)
    
    fig.update_layout(height=800, title_text=title)
    return fig

Also applies to: 645-686

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e601a1c and d411807.

⛔ Files ignored due to path filters (7)
  • Cargo.toml is excluded by !**/*.toml
  • exchanges/binance/Cargo.toml is excluded by !**/*.toml
  • exchanges/bitbank/Cargo.toml is excluded by !**/*.toml
  • modules/rbot_lib/Cargo.toml is excluded by !**/*.toml
  • modules/rbot_lib/src/common/exchange.json is excluded by !**/*.json
  • package-lock.json is excluded by !**/package-lock.json, !**/*.json
  • package.json is excluded by !**/*.json
📒 Files selected for processing (34)
  • doc/environment.md (1 hunks)
  • exchanges/binance/src/config.rs (1 hunks)
  • exchanges/binance/src/rest.rs (0 hunks)
  • exchanges/binance/src/ws.rs (6 hunks)
  • exchanges/bitbank/src/lib.rs (1 hunks)
  • exchanges/bitbank/src/market.rs (1 hunks)
  • exchanges/bitbank/src/message.rs (2 hunks)
  • exchanges/bitbank/src/rest.rs (7 hunks)
  • exchanges/bitbank/src/socket.rs (1 hunks)
  • exchanges/bitbank/src/ws.rs (1 hunks)
  • exchanges/bitflyer/src/market.rs (1 hunks)
  • exchanges/bybit/src/config.rs (1 hunks)
  • exchanges/bybit/src/market.rs (3 hunks)
  • exchanges/bybit/src/rest.rs (1 hunks)
  • exchanges/bybit/src/ws.rs (2 hunks)
  • modules/rbot_lib/src/common/bar.rs (4 hunks)
  • modules/rbot_lib/src/common/ccxt_config.rs (4 hunks)
  • modules/rbot_lib/src/common/config.rs (1 hunks)
  • modules/rbot_lib/src/common/env.rs (6 hunks)
  • modules/rbot_lib/src/common/order.rs (1 hunks)
  • modules/rbot_lib/src/db/archive.rs (2 hunks)
  • modules/rbot_lib/src/db/df.rs (2 hunks)
  • modules/rbot_lib/src/net/ws.rs (15 hunks)
  • modules/rbot_market/src/market.rs (2 hunks)
  • modules/rbot_session/src/runner.rs (2 hunks)
  • modules/rbot_session/src/session.rs (2 hunks)
  • python/rbot/__init__.py (2 hunks)
  • src/lib.rs (2 hunks)
  • test/00_suite/10_ccxt/test_ccxt_config_generate.py (1 hunks)
  • test/00_suite/test_00exchange.py (1 hunks)
  • test/00_suite/test_01market_basic.py (2 hunks)
  • test/bitbank_test/basilbot_backtest.ipynb (1 hunks)
  • test/bitbank_test/download.py (1 hunks)
  • test/bitbank_test/nullagent.py (1 hunks)
💤 Files with no reviewable changes (1)
  • exchanges/binance/src/rest.rs
🧰 Additional context used
🪛 Ruff (0.11.9)
test/00_suite/test_00exchange.py

3-3: rbot.init_debug_log imported but unused

Remove unused import: rbot.init_debug_log

(F401)

python/rbot/__init__.py

5-5: rbot may be undefined, or defined from star imports

(F405)


6-6: rbot may be undefined, or defined from star imports

(F405)

test/bitbank_test/download.py

3-3: rbot.init_log imported but unused

Remove unused import

(F401)


3-3: rbot.init_debug_log imported but unused

Remove unused import

(F401)

test/bitbank_test/nullagent.py

2-2: rbot.Session imported but unused

Remove unused import: rbot.Session

(F401)


7-7: rbot.init_debug_log imported but unused

Remove unused import: rbot.init_debug_log

(F401)


9-9: rbot.OrderSide imported but unused

Remove unused import: rbot.OrderSide

(F401)


11-11: rbot.NOW imported but unused

Remove unused import

(F401)


11-11: rbot.DAYS imported but unused

Remove unused import

(F401)

🪛 markdownlint-cli2 (0.17.2)
doc/environment.md

7-7: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: linux-simple
🔇 Additional comments (46)
exchanges/bybit/src/config.rs (1)

4-4: 未使用のインポートの削除を承認

FeeTypeのインポートが削除されていますが、このファイル内ではコメントアウトされたコード内でのみ使用されており、アクティブなコードでは使用されていません。これは適切なコードクリーンアップです。

modules/rbot_lib/src/common/config.rs (1)

126-126: Pythonバインディングの機能向上を承認

FeeType enumにeq_int属性が追加されました。これによりPythonでの等価比較が整数値ベースで実行可能になり、Pythonバインディングの使いやすさが向上します。他のenumでも同様の変更が行われており、一貫性のある改善です。

python/rbot/__init__.py (2)

5-6: 型チェック警告の適切な抑制を承認

star importsに起因する型チェック警告を# type: ignoreコメントで適切に抑制しています。これは静的解析ツールのF405警告に対する正しい対処法です。

🧰 Tools
🪛 Ruff (0.11.9)

5-5: rbot may be undefined, or defined from star imports

(F405)


6-6: rbot may be undefined, or defined from star imports

(F405)


35-35: コピーライト年の更新を承認

コピーライト表示が2022-2025年に更新されました。これは適切な更新です。

src/lib.rs (2)

13-13: Bitbankクラスのインポートを承認

PRの目的であるBitbank取引所サポートの一環として、Bitbankクラスが適切にインポートされています。既存のexchangeクラスと同じパターンに従っています。


78-78: PythonバインディングへのBitbankクラス追加を承認

BitbankクラスがPythonモジュールに正しく追加されました。これによりPythonコードからBitbank取引所の機能にアクセス可能になります。既存のBinanceやBybitクラスと一貫したパターンで実装されています。

test/00_suite/10_ccxt/test_ccxt_config_generate.py (1)

92-95: Bitbank ブランチの整形と情報不足を修正してください

  • public_ws_server / private_ws_server 行が他のブランチより 4 スペース深く、読みやすさが低下します。
  • historical_web_base が空文字のままです。他の取引所同様、過去データのベース URL を設定するか、不要ならコメントで理由を補足してください。
-        elif self.exchange_name == 'bitbank':
-                public_ws_server = "wss://stream.bitbank.cc/socket.io/?EIO=4&transport=websocket"
-                private_ws_server = "wss://stream.bitbank.cc/v1/private"
+        elif self.exchange_name == 'bitbank':
+            historical_web_base = "https://public.bitbank.cc"  # 例: 必要に応じ変更
+            public_ws_server = "wss://stream.bitbank.cc/socket.io/?EIO=4&transport=websocket"
+            private_ws_server = "wss://stream.bitbank.cc/v1/private"

[ suggest_nitpick ]

test/00_suite/test_00exchange.py (2)

3-3: 未使用の init_debug_log を削除してください

init_debug_log は本テスト内で呼び出されておらず、Ruff の F401 警告が出ています。不要なら import を削除、使用する場合はテスト内で呼び出してください。
[ suggest_nitpick ]

🧰 Tools
🪛 Ruff (0.11.9)

3-3: rbot.init_debug_log imported but unused

Remove unused import: rbot.init_debug_log

(F401)


11-14: パラメータ化ケースの順序重複に注意

Binance(True) が 2 度出現しているように見えます(行 10 と 11)。重複するとテスト実行時間が増えるだけなので整理をご検討ください。
[ suggest_nitpick ]

modules/rbot_lib/src/common/order.rs (1)

256-265: #[pyclass(eq_int)] 追加時は Python 側の型互換性も確認を

eq_int により Python で LogStatus == 0 のような比較が可能になりますが、eq を付けない場合 Rust 同士の比較にしか対応しません。また、Python から整数への暗黙変換を行う __int__ 実装が無いので、必要なら追加をご検討ください。

例:

#[pymethods]
impl LogStatus {
    fn __int__(&self) -> u8 {
        *self as u8
    }
}

[ request_verification ][ suggest_optional_refactor ]

modules/rbot_lib/src/db/df.rs (2)

5-5: 未使用のimportの削除が適切です

Pathのimportが削除され、実際に使用されているPathBufのみが残されています。コードの整理として良い変更です。


617-617: 不要なclone()呼び出しの削除によりパフォーマンスが向上します

rename()メソッドはselfを返すため、.clone()呼び出しは不要でした。この削除により無駄なメモリ割り当てが回避されます。

exchanges/binance/src/config.rs (1)

6-7: importの整理により可読性が向上しています

未使用のimportが削除され、実際に使用されているMarketConfigExchangeConfigのみが残されています。コードの整理として適切な変更です。

test/bitbank_test/download.py (1)

7-15: テストの実装が適切です

Bitbank APIの基本的な使用方法が適切に実装されています。データダウンロード機能の動作確認として有用なテストファイルです。

exchanges/bitbank/src/lib.rs (2)

3-5: 新しいモジュールの追加が適切に行われています

marketwssocketモジュールが追加され、Bitbank取引所の機能が拡張されています。モジュール構成が論理的で整理されています。


9-11: 公開API拡張が適切に実装されています

新しく追加されたモジュールが適切に再エクスポートされ、ライブラリの公開APIが拡張されています。Bitbank取引所の完全なサポートに必要な機能が提供されています。

modules/rbot_market/src/market.rs (1)

851-853: 時間範囲フィルタリングの追加は適切です。

Klineから変換されたトレードデータが指定された時間範囲内にあることを保証する良い変更です。開始時刻を含み、終了時刻を含まない(半開区間)という一般的なパターンを使用しています。

modules/rbot_session/src/session.rs (1)

6-6: Pythonバインディングの改善が適切に実装されています。

IntoPyObjectのインポート追加と、ExecuteMode列挙型へのeq, eq_int属性の追加により、Python側での等価比較が可能になります。これらの変更はPythonとの相互運用性を向上させます。

Also applies to: 28-28

exchanges/binance/src/ws.rs (1)

322-331: テストに検証を追加しましょう
test_make_connect_url は URL を表示するだけでアサーションが無く、失敗を検知できません。
生成された URL が

  1. "wss://" で始まる
  2. listenKey= を含む
    など最低限の条件を assert! で確認してください。
    加えて、API キー未設定環境では create_listen_key が失敗し CI が落ちる可能性があります。
    dotenv でキーが無い場合は return Ok(()) として #[ignore] マークを付ける等の配慮を推奨します。
exchanges/bybit/src/rest.rs (1)

168-170: 不要な mut を削除した判断に賛成です
trades を変更していないため immut 化は適切で、将来の意図しない再代入も防げます。

test/00_suite/test_01market_basic.py (3)

2-2: インポートの簡素化を承認します。

設定オブジェクトから文字列識別子への移行により、よりシンプルなインターフェースになりました。


9-14: Bitbank取引所のテストケース追加を承認します。

文字列識別子を使用した新しいパラメータ形式への移行とBitbank取引所のテストケース追加により、テストカバレッジが向上しています。

Also applies to: 41-46


51-51: init_debug_log()の呼び出し順序を確認してください。

init_debug_log()open_market()の後に呼び出されているため、マーケット初期化中のログが記録されない可能性があります。

マーケット初期化時のログ出力が必要かどうか確認し、必要であれば以下のように修正してください:

 def test_open_market_stream(exchange, config):
+    init_debug_log()
     market = exchange.open_market(config)
     
-    init_debug_log()
exchanges/bitflyer/src/market.rs (1)

111-112:

Details

✅ Verification successful

APIシグネチャの変更が他の取引所と一貫性があることを確認してください。

open_marketメソッドのパラメータが&MarketConfigから&strに変更されています。この変更により、インターフェースが簡素化されますが、他の取引所の実装と一貫性があることを確認する必要があります。

以下のスクリプトで他の取引所のopen_marketメソッドのシグネチャを確認します:


🏁 Script executed:

#!/bin/bash
# Description: 他の取引所のopen_marketメソッドのシグネチャを確認

# 各取引所のopen_marketメソッドを検索
ast-grep --pattern 'pub fn open_market(&self, $_) -> $_'

Length of output: 58


前回の ast-grep では一致が検出できなかったため、ripgrep を使って他の取引所でも open_market メソッドのシグネチャを再検索します。


🏁 Script executed:

#!/bin/bash
# exchanges/**/src/market.rs 内の pub fn open_market を検索
rg "pub fn open_market" -n exchanges/

Length of output: 478


open_market メソッドのシグネチャは他の取引所と一致しています

– Bybit, Bitbank, Binance でも同様に
pub fn open_market(&self, symbol: &str) -> …
が使われていることを確認しました。

この変更はインターフェースの簡素化であり、他の実装と一貫性が取れているため問題ありません。

modules/rbot_lib/src/common/env.rs (3)

23-23: 環境変数ファイルパスの変更を確認してください

RBOT_ENV_FILE.rusty-bot/.envに設定されていますが、これは相対パスです。dot_env_reader関数ではhome_dirと結合されて使用されているため問題ありませんが、この変更が既存のユーザー設定に影響を与える可能性があります。

移行ガイドやドキュメントの更新が必要かもしれません。


28-29: 大文字変換の追加は良い改善です

exchange_nameを大文字に変換することで、環境変数名の一貫性が保たれ、大文字小文字の違いによる設定ミスを防ぐことができます。


156-177: PyO3 APIの更新に対応した適切な変更です

PyModule::from_code_boundからPyModule::from_codeへの変更と、c_str!マクロの使用は、PyO3の新しいAPIに適切に対応しています。

exchanges/bybit/src/market.rs (2)

106-114: 新しい client_order_id 引数の追加、良い改善です

Python から None を指定可能になり、柔軟性が向上しました。
pyo3(signature=...) でデフォルト値を明示している点も 👍


121-128: market_order も同様に対応済み

limit_order とインターフェースを揃えており、一貫性があります。

modules/rbot_lib/src/net/ws.rs (4)

66-66: socket.ioクライアントサポートの追加を承認します

SimpleWebsocketAutoConnectClient構造体にsocket_io_clientフィールドを追加することで、socket.ioプロトコル特有の制御メッセージを適切に処理できるようになります。

Also applies to: 354-354


141-154: socket.io接続時の制御メッセージスキップ処理を承認します

socket.ioクライアントモードでは、接続時の制御メッセージを適切にスキップする実装になっています。また、message.len() > 0のチェックも追加されており、空のメッセージリストに対する安全性が向上しています。


258-269: close()メソッドの安全性改善を承認します

write_streamSomeであることを確認してからクローズ処理を行うように修正されており、潜在的なパニックを防ぐ良い改善です。


743-743: テストコードの適切な更新を承認します

すべてのテストケースでsocket_io_clientパラメータにfalseを渡すことで、既存の動作を維持しています。

Also applies to: 778-778, 807-807, 852-852

test/bitbank_test/basilbot_backtest.ipynb (1)

261-273:

Details

✅ Verification successful

Jupyter環境の設定確認が必要です

IProgress not foundエラーが発生しています。これはJupyter環境の問題です。

以下のコマンドを実行して、必要なパッケージをインストールしてください:

また、Jupyter環境で以下を実行してください:

!jupyter nbextension enable --py widgetsnbextension

Also applies to: 349-361


🏁 Script executed:

#!/bin/bash
# Jupyterウィジェットの依存関係を確認
pip list | grep -E "(ipywidgets|jupyter)" || echo "ipywidgets not installed"

# 必要なパッケージをインストール
pip install --upgrade ipywidgets jupyter

Length of output: 19389


Jupyterウィジェット拡張機能を有効化してください

既に ipywidgetsjupyter のインストールは完了しているため、後続のエラー解消には nbextension の有効化が必要です。ターミナルで以下を実行してください:

jupyter nbextension enable --py widgetsnbextension --sys-prefix

• JupyterLab (4.x 以上) をご利用の場合、追加の labextension は不要です。
• 上記実行後はノートブックサーバーを再起動し、キャッシュクリアのためブラウザもリロードしてください。

exchanges/bitbank/src/ws.rs (1)

57-67: socket.ioクライアントとしての設定を承認します

BitbankのWebSocketサーバーがsocket.ioプロトコルを使用しているため、AutoConnectClienttrueを渡す設定は適切です。

exchanges/bitbank/src/message.rs (5)

15-17: タイムスタンプ変換関数は正しく実装されています。

ミリ秒からマイクロ秒への変換が適切に行われています。


19-24: REST APIレスポンス構造体の定義は適切です。

シンプルで明確な構造になっています。


52-67: 注文ステータスのマッピング関数は適切に実装されています。

未知のステータスに対するエラーログ出力も含まれており、デバッグに役立ちます。


68-111: BitbankOrderからOrderへの変換実装は適切です。

必要なフィールドが正しくマッピングされています。


333-478: テストモジュールは包括的で適切に実装されています。

様々なメッセージタイプのパースをカバーしており、品質保証に貢献しています。

exchanges/bitbank/src/market.rs (2)

551-565: 時間範囲の調整ロジックは適切です。

無効な開始時刻や古すぎるデータへのアクセスを防ぐ良い実装です。


482-482:

Details

❌ Incorrect review comment

WebSocket接続のコードがコメントアウトされています。

public_ws.connect().awaitがコメントアウトされていますが、WebSocketクライアントの実装によっては明示的な接続が必要な場合があります。


🏁 Script executed:

#!/bin/bash
# BitbankPublicWsClientのopen_stream実装を確認して、内部でconnectを呼んでいるか検証
ast-grep --pattern 'impl $_ for BitbankPublicWsClient {
  $$$
  async fn open_stream($$$) {
    $$$
  }
  $$$
}'

Length of output: 114


さらなる検証が必要です。async fn open_stream の定義箇所と BitbankPublicWsClient 内で connect を呼び出しているかを検索してください。


🏁 Script executed:

#!/bin/bash
# open_streamの定義を探す
rg "async fn open_stream" -n .

# BitbankPublicWsClientの実装を探す
rg "struct BitbankPublicWsClient" -n -A3 .

# connect呼び出しを含む実装箇所を探す
rg "BitbankPublicWsClient.*connect" -n .

Length of output: 1048


さらなる情報収集のため、BitbankPublicWsClientopen_stream 実装を直接確認します。


🏁 Script executed:

#!/bin/bash
# impl BitbankPublicWsClientブロック内を表示
rg -n "impl .*BitbankPublicWsClient" -n -A20 -B5 exchanges/bitbank/src/ws.rs

Length of output: 2062


BitbankPublicWsClient の実際の open_stream 実装内で connect が呼ばれているかを確認するため、該当箇所を抜粋表示してください。


🏁 Script executed:

#!/bin/bash
# exchanges/bitbank/src/ws.rs の pub async fn open_stream 実装を表示
rg -n "pub async fn open_stream" -n -A50 -B5 exchanges/bitbank/src/ws.rs

Length of output: 4336


AutoConnectClient の実装を確認し、open_stream 内で connect が呼ばれているか調べます。


🏁 Script executed:

#!/bin/bash
# AutoConnectClientのopen_stream実装を表示
rg -n "pub async fn open_stream" -n -A30 -B5 modules/rbot_lib/src/net/ws.rs

# AutoConnectClientのconnect実装を表示
rg -n "async fn connect" -n -A20 -B5 modules/rbot_lib/src/net/ws.rs

Length of output: 3655


async_start_market_stream メソッド内で public_ws.connect().await コメントアウト前後の処理を確認します。


🏁 Script executed:

#!/bin/bash
# async_start_market_stream の定義と前後50行を表示
rg -n "async fn async_start_market_stream" -n -A50 -B5 exchanges/bitbank/src/market.rs

Length of output: 2093


public_ws.connect() の明示的呼び出しは不要です

AutoConnectClient の open_stream() 内で最初の receive_text() 呼び出し時に self.connect().await が実行されるため、public_ws.connect().await を別途呼び出す必要はありません。このままコメントアウトで問題ありません。

Likely an incorrect or invalid review comment.

exchanges/bitbank/src/rest.rs (4)

76-93: get_recent_tradesメソッドは適切に実装されています。

エラーハンドリングも含めて正しく実装されています。


149-151: サポートされていない機能に対する警告は適切です。

ユーザーにclient_order_idがサポートされていないことを明確に伝えています。


328-330: APIレスポンスのエラーチェックが適切に実装されています。

successフラグを確認してエラーを返す実装は良いプラクティスです。


441-615: テストモジュールは包括的でよく構成されています。

主要なAPIエンドポイントがカバーされており、統合テストとして機能します。

Comment on lines 343 to 347
let kwargs =
vec![("connect_ws", true), ("verbose", self.verbose)];

let kwargs = kwargs.into_py_dict_bound(py);
let kwargs = kwargs.into_py_dict(py)?;
market.call_method("download", (5, ), Some(&kwargs))?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

into_py_dict の戻り値に ? は不要では?
IntoPyDict::into_py_dict(py)&PyDict を返し Result ではありません。
? を付けるとコンパイルエラーになります。

-let kwargs = kwargs.into_py_dict(py)?;
+let kwargs = kwargs.into_py_dict(py);

コンパイルを確認してください。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let kwargs =
vec![("connect_ws", true), ("verbose", self.verbose)];
let kwargs = kwargs.into_py_dict_bound(py);
let kwargs = kwargs.into_py_dict(py)?;
market.call_method("download", (5, ), Some(&kwargs))?;
let kwargs =
vec![("connect_ws", true), ("verbose", self.verbose)];
let kwargs = kwargs.into_py_dict(py);
market.call_method("download", (5, ), Some(&kwargs))?;
🤖 Prompt for AI Agents
In modules/rbot_session/src/runner.rs around lines 343 to 347, the code calls
into_py_dict(py) on a vector, which returns a reference to PyDict and not a
Result. The use of ? operator is incorrect here and will cause a compilation
error. Remove the ? operator from the line assigning kwargs to avoid this error
and ensure the code compiles correctly.

Comment on lines +63 to +67
bitbank.enable_order_with_my_own_risk = True

runner = Runner()
session = runner.real_run(
exchange=bitbank, market=market, agent=agent, verbose=True, execute_time=60*3, log_memory=True)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

実際の取引を行うテストは財務リスクがあります!

このテストはreal_run()を使用して実際の取引を実行しており、enable_order_with_my_own_risk = Trueが設定されているため、実際の資金損失が発生する可能性があります。

テスト環境では以下のいずれかを使用することを強く推奨します:

  • back_test(): 過去データでのバックテスト
  • dry_run(): 実際の注文を出さないドライラン

安全なテスト方法に変更してください:

-bitbank.enable_order_with_my_own_risk = True
-
-runner = Runner()
-session = runner.real_run(
-        exchange=bitbank, market=market, agent=agent, verbose=True, execute_time=60*3, log_memory=True)
+# テスト環境ではドライランを使用
+runner = Runner()
+session = runner.dry_run(
+        exchange=bitbank, market=market, agent=agent, verbose=True, execute_time=60*3, log_memory=True)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bitbank.enable_order_with_my_own_risk = True
runner = Runner()
session = runner.real_run(
exchange=bitbank, market=market, agent=agent, verbose=True, execute_time=60*3, log_memory=True)
# テスト環境ではドライランを使用
runner = Runner()
session = runner.dry_run(
exchange=bitbank, market=market, agent=agent, verbose=True, execute_time=60*3, log_memory=True)
🤖 Prompt for AI Agents
In test/bitbank_test/nullagent.py around lines 63 to 67, the code performs an
actual trading test using real_run() with enable_order_with_my_own_risk set to
True, which poses a financial risk. Replace the real_run() call with either
back_test() or dry_run() to ensure the test is safe and does not involve real
transactions. This change will prevent potential financial loss during testing.

Comment on lines +261 to 265
let py_script = CString::new(py_script.as_str()).unwrap();

let py_module =
PyModule::from_code_bound(py, &py_script, "py_running_bar.py", "py_running_bar");
PyModule::from_code(py, &py_script, c_str!("py_running_bar.py"), c_str!("py_running_bar"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

致命的: PyRunningBar::init はコンパイル不能です

PyModule::from_code の第 2 引数は &[u8] 互換ですが、現在渡している &CStringAsRef<[u8]> を実装していません。
そのためビルド時に型エラーになります。

- let py_module =
-     PyModule::from_code(py, &py_script, c_str!("py_running_bar.py"), c_str!("py_running_bar"));
+ let py_module = PyModule::from_code(
+     py,
+     py_script.as_c_str(),       // または `py_script.to_bytes()`
+     c_str!("py_running_bar.py"),
+     c_str!("py_running_bar"),
+ );

他の2メソッド(RestBar / FileBar)が as_c_str() を使っている点とも統一してください。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let py_script = CString::new(py_script.as_str()).unwrap();
let py_module =
PyModule::from_code_bound(py, &py_script, "py_running_bar.py", "py_running_bar");
PyModule::from_code(py, &py_script, c_str!("py_running_bar.py"), c_str!("py_running_bar"));
let py_script = CString::new(py_script.as_str()).unwrap();
let py_module = PyModule::from_code(
py,
py_script.as_c_str(), // または `py_script.to_bytes()`
c_str!("py_running_bar.py"),
c_str!("py_running_bar"),
);
🤖 Prompt for AI Agents
In modules/rbot_lib/src/common/bar.rs around lines 261 to 265, the code passes a
&CString to PyModule::from_code, but this function expects a &[u8] or similar
type, and &CString does not implement AsRef<[u8]>. To fix this, convert
py_script to a byte slice using py_script.as_bytes() before passing it to
PyModule::from_code. Also, update other methods (RestBar / FileBar) to use
as_c_str() for consistency.

Comment on lines +103 to +118
fn get_market_json_by_native_symbol(exchange_name: &str, category: &str, native_symbol: &str) -> anyhow::Result<MarketJson> {
let native_symbol = native_symbol.to_uppercase();

let exchange_config = get_exchange_config(exchange_name)?;

for market in exchange_config.markets {
if market.trade_category == category && market.trade_symbol == native_symbol {
return Ok(market);
}
}

Err(anyhow!(
"not found market ({}) in exchange({})",
native_symbol,
exchange_name
))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

ネイティブシンボルの前後空白が処理されず、検索に失敗します

native_symbol.to_uppercase() だけでは " BTCUSDT" のような文字列を正規化できず、
JSON 内の "BTCUSDT" と一致しません。結果として本関数は常に Err を返し、
後続の get_market_config_by_native_symbol とテスト test_get_market_config_by_native_symbol が失敗します。

- let native_symbol = native_symbol.to_uppercase();
+ let native_symbol = native_symbol.trim().to_uppercase();

同様に category も大小文字を無視した比較 (eq_ignore_ascii_case) を推奨します。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn get_market_json_by_native_symbol(exchange_name: &str, category: &str, native_symbol: &str) -> anyhow::Result<MarketJson> {
let native_symbol = native_symbol.to_uppercase();
let exchange_config = get_exchange_config(exchange_name)?;
for market in exchange_config.markets {
if market.trade_category == category && market.trade_symbol == native_symbol {
return Ok(market);
}
}
Err(anyhow!(
"not found market ({}) in exchange({})",
native_symbol,
exchange_name
))
fn get_market_json_by_native_symbol(
exchange_name: &str,
category: &str,
native_symbol: &str,
) -> anyhow::Result<MarketJson> {
let native_symbol = native_symbol.trim().to_uppercase();
let exchange_config = get_exchange_config(exchange_name)?;
for market in exchange_config.markets {
if market.trade_category == category && market.trade_symbol == native_symbol {
return Ok(market);
}
}
Err(anyhow!(
"not found market ({}) in exchange({})",
native_symbol,
exchange_name
))
}
🤖 Prompt for AI Agents
In modules/rbot_lib/src/common/ccxt_config.rs around lines 103 to 118, the
function get_market_json_by_native_symbol does not trim whitespace from
native_symbol before comparison, causing search failures when native_symbol has
leading or trailing spaces. To fix this, trim whitespace from native_symbol
using trim() and convert to uppercase, then compare with market.trade_symbol
also normalized similarly if needed. Additionally, consider using
eq_ignore_ascii_case for category comparison to ignore case differences. This
will ensure accurate matching regardless of whitespace or case variations.

Comment on lines +290 to 309
Message::Text(mut t) => {
// SOcket IO response
if t.starts_with("2") { // ping
log::warn!("message: {:?}", t);
self.send_text("3".to_string()).await;
continue;
}

if t.starts_with("0") { // connect
log::warn!("message: {:?}", t);
self.send_text("40".to_string()).await; // connect response connect
continue;
}
let mut t = t.to_string();
if t.starts_with("42") { // event message
t = t.trim_start_matches("42").to_string();
}

return Ok(ReceiveMessage::Text(t));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

socket.ioメッセージ処理に改善が必要です

socket.ioプロトコルの処理は正しく実装されていますが、以下の改善を推奨します:

  1. log::warn!ではなくlog::debug!を使用すべきです(これらは通常の動作であり警告ではありません)
  2. socket.io特有の処理はself.socket_io_clientがtrueの場合のみ実行すべきです
                 Message::Text(mut t) => {
-                    // SOcket IO response
-                    if t.starts_with("2") { // ping
-                        log::warn!("message: {:?}", t);
-                        self.send_text("3".to_string()).await;
-                        continue;
-                    }
-
-                    if t.starts_with("0") { // connect
-                        log::warn!("message: {:?}", t);
-                        self.send_text("40".to_string()).await; // connect response connect
-                        continue;
-                    }
-                    let mut t = t.to_string();
-                    if t.starts_with("42") { // event message
-                        t = t.trim_start_matches("42").to_string();
-                    }
+                    // Socket.IO response handling
+                    if self.socket_io_client {
+                        if t.starts_with("2") { // ping
+                            log::debug!("Socket.IO ping: {:?}", t);
+                            self.send_text("3".to_string()).await;
+                            continue;
+                        }
+
+                        if t.starts_with("0") { // connect
+                            log::debug!("Socket.IO connect: {:?}", t);
+                            self.send_text("40".to_string()).await;
+                            continue;
+                        }
+                        
+                        if t.starts_with("42") { // event message
+                            t = t.trim_start_matches("42").to_string();
+                        }
+                    }

                     return Ok(ReceiveMessage::Text(t));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Message::Text(mut t) => {
// SOcket IO response
if t.starts_with("2") { // ping
log::warn!("message: {:?}", t);
self.send_text("3".to_string()).await;
continue;
}
if t.starts_with("0") { // connect
log::warn!("message: {:?}", t);
self.send_text("40".to_string()).await; // connect response connect
continue;
}
let mut t = t.to_string();
if t.starts_with("42") { // event message
t = t.trim_start_matches("42").to_string();
}
return Ok(ReceiveMessage::Text(t));
}
Message::Text(mut t) => {
- // SOcket IO response
- if t.starts_with("2") { // ping
- log::warn!("message: {:?}", t);
- self.send_text("3".to_string()).await;
- continue;
- }
-
- if t.starts_with("0") { // connect
- log::warn!("message: {:?}", t);
- self.send_text("40".to_string()).await; // connect response connect
- continue;
- }
- let mut t = t.to_string();
- if t.starts_with("42") { // event message
- t = t.trim_start_matches("42").to_string();
- }
+ // Socket.IO response handling
+ if self.socket_io_client {
+ if t.starts_with("2") { // ping
+ log::debug!("Socket.IO ping: {:?}", t);
+ self.send_text("3".to_string()).await;
+ continue;
+ }
+
+ if t.starts_with("0") { // connect
+ log::debug!("Socket.IO connect: {:?}", t);
+ self.send_text("40".to_string()).await;
+ continue;
+ }
+
+ if t.starts_with("42") { // event message
+ t = t.trim_start_matches("42").to_string();
+ }
+ }
return Ok(ReceiveMessage::Text(t));
}
🤖 Prompt for AI Agents
In modules/rbot_lib/src/net/ws.rs around lines 290 to 309, the socket.io message
handling logs messages at the warn level, which is inappropriate for normal
protocol messages, and does not check if the socket.io client mode is active.
Change the log level from warn to debug for these messages, and add a condition
to execute this block only if self.socket_io_client is true to ensure correct
protocol handling.

Comment on lines +261 to +262
let message = message.get(1).unwrap().clone();
let room_name = message.get("room_name").unwrap().as_str().unwrap();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

unwrap()の使用によりパニックが発生する可能性があります。

メッセージ形式が期待と異なる場合の適切なエラーハンドリングが必要です。

-        let message = message.get(1).unwrap().clone();
-        let room_name = message.get("room_name").unwrap().as_str().unwrap();
+        let message = message.get(1)
+            .ok_or_else(|| anyhow::anyhow!("Missing message at index 1"))?
+            .clone();
+        let room_name = message.get("room_name")
+            .ok_or_else(|| anyhow::anyhow!("Missing room_name field"))?
+            .as_str()
+            .ok_or_else(|| anyhow::anyhow!("room_name is not a string"))?;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let message = message.get(1).unwrap().clone();
let room_name = message.get("room_name").unwrap().as_str().unwrap();
let message = message.get(1)
.ok_or_else(|| anyhow::anyhow!("Missing message at index 1"))?
.clone();
let room_name = message.get("room_name")
.ok_or_else(|| anyhow::anyhow!("Missing room_name field"))?
.as_str()
.ok_or_else(|| anyhow::anyhow!("room_name is not a string"))?;
🤖 Prompt for AI Agents
In exchanges/bitbank/src/message.rs at lines 261-262, the use of unwrap() on
message.get(1) and message.get("room_name") can cause panics if the values are
missing or not in the expected format. Replace unwrap() calls with proper error
handling, such as using match or if let to handle None or unexpected types
gracefully, and provide meaningful error messages or fallback behavior.

Comment on lines +140 to +161
impl Into<BoardTransfer> for BitbankDepth {
fn into(self) -> BoardTransfer {
let mut board = BoardTransfer::new();
board.asks = self
.asks
.into_iter()
.map(|a| BoardItem {
price: Decimal::from_str(&a[0]).unwrap(),
size: Decimal::from_str(&a[1]).unwrap(),
})
.collect();
board.bids = self
.bids
.into_iter()
.map(|b| BoardItem {
price: Decimal::from_str(&b[0]).unwrap(),
size: Decimal::from_str(&b[1]).unwrap(),
})
.collect();
board
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

文字列からDecimalへの変換でunwrap()を使用すると、パニックが発生する可能性があります。

APIレスポンスの形式が変更された場合や不正なデータが含まれている場合、アプリケーションがクラッシュする恐れがあります。エラーハンドリングを追加することを推奨します。

-            .map(|a| BoardItem {
-                price: Decimal::from_str(&a[0]).unwrap(),
-                size: Decimal::from_str(&a[1]).unwrap(),
-            })
+            .map(|a| BoardItem {
+                price: Decimal::from_str(&a[0]).map_err(|e| anyhow::anyhow!("Failed to parse ask price: {}", e))?,
+                size: Decimal::from_str(&a[1]).map_err(|e| anyhow::anyhow!("Failed to parse ask size: {}", e))?,
+            })

同様の変更をbidsの処理にも適用してください。ただし、IntoトレイトはResultを返せないため、TryFromトレイトの使用を検討してください。

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In exchanges/bitbank/src/message.rs lines 140 to 161, the code uses unwrap() on
the result of Decimal::from_str, which can cause a panic if the string is
invalid. Replace the unwrap() calls with proper error handling, such as using
try_from or returning a Result to handle potential parsing errors gracefully.
Since Into<BoardTransfer> cannot return a Result, consider implementing
TryFrom<BitbankDepth> for BoardTransfer instead to handle errors properly.

let message: Vec<Value> = json5::from_str(message)?;

if let Some(event_type) = message.get(0).and_then(|v| v.as_str()) {
println!("Event type: {}", event_type);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

デバッグ出力にprintln!を使用しています。

本番環境ではlog::debug!log::trace!を使用することを推奨します。

-            println!("Event type: {}", event_type);
+            log::debug!("Event type: {}", event_type);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
println!("Event type: {}", event_type);
log::debug!("Event type: {}", event_type);
🤖 Prompt for AI Agents
In exchanges/bitbank/src/message.rs at line 258, the code uses println! for
debugging output, which is not suitable for production. Replace println! with
log::debug! or log::trace! to enable configurable logging levels and better
control over debug information in production environments.

Comment thread exchanges/bitbank/src/market.rs
Comment thread exchanges/bitbank/src/rest.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🔭 Outside diff range comments (2)
exchanges/bitbank/src/rest.rs (2)

236-268: ⚠️ Potential issue

logdf_to_archivedfメソッドが未実装

todo!()マクロが使用されており、実行時にパニックが発生します。実装を完成させるか、明確なエラーメッセージを返すようにしてください。

このメソッドの実装を支援しますか?BitbankのDataFrameフォーマットをアーカイブ形式に変換する実装を提供できます。


95-108: 🛠️ Refactor suggestion

時間範囲でのトレード取得がサポートされていない

警告ログのみで空のベクターを返していますが、呼び出し側に明確にエラーを伝えるべきです。

-        log::warn!("Bitbank does not support getting trades by time range");
-        Ok((vec![], RestPage::Done))
+        Err(anyhow::anyhow!("Bitbank does not support getting trades by time range. Use get_recent_trades() instead."))
♻️ Duplicate comments (5)
exchanges/bitbank/src/message.rs (4)

140-161: 文字列からDecimalへの変換でunwrap()を使用すると、パニックが発生する可能性があります。

APIレスポンスの形式が変更された場合や不正なデータが含まれている場合、アプリケーションがクラッシュする恐れがあります。TryFromトレイトの使用を検討してください。


163-168: JSONデシリアライゼーションでunwrap()を使用しています。

データ形式が期待と異なる場合にパニックが発生します。TryFromトレイトの使用を検討してください。


265-265: デバッグ出力にprintln!を使用しています。

本番環境ではlog::debug!log::trace!を使用することを推奨します。


268-269: unwrap()の使用によりパニックが発生する可能性があります。

メッセージ形式が期待と異なる場合の適切なエラーハンドリングが必要です。

exchanges/bitbank/src/rest.rs (1)

213-224: get_accountメソッドが未完成です。

現在は空のAccountCoinsを返していますが、実際のアカウントデータをパースする必要があります。

🧹 Nitpick comments (2)
exchanges/bitbank/src/socket.rs (1)

13-37: コメントアウトされたテストコードの削除

使用されていないコメントアウトされたテストコードは削除することを推奨します。

exchanges/bitbank/src/rest.rs (1)

149-151: 未サポート機能の警告が不十分

client_order_idがサポートされていないことを警告していますが、呼び出し側にエラーとして通知すべきです。

         if let Some(id) = client_order_id {
-            log::warn!("client_order_id is not supported in bitbank");
+            return Err(anyhow::anyhow!("client_order_id is not supported in Bitbank"));
         }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d411807 and f498f03.

⛔ Files ignored due to path filters (2)
  • Cargo.toml is excluded by !**/*.toml
  • exchanges/bitbank/Cargo.toml is excluded by !**/*.toml
📒 Files selected for processing (3)
  • exchanges/bitbank/src/message.rs (2 hunks)
  • exchanges/bitbank/src/rest.rs (7 hunks)
  • exchanges/bitbank/src/socket.rs (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: linux-simple

Comment thread exchanges/bitbank/src/socket.rs Outdated
Comment thread exchanges/bitbank/src/socket.rs Outdated
use pubnub::PubNubClientBuilder;
use tracing::subscriber::NoSubscriber;

const SUBSCRIBER_KEY: &str = "sub-c-ecebae8e-dd60-11e6-b6b1-02ee2ddab7fe";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

セキュリティリスク:ハードコードされた認証情報

実際のサブスクライバーキーがハードコードされています。環境変数または設定ファイルから読み込むように変更してください。

-const SUBSCRIBER_KEY: &str = "sub-c-ecebae8e-dd60-11e6-b6b1-02ee2ddab7fe";
+const SUBSCRIBER_KEY: &str = env!("PUBNUB_SUBSCRIBER_KEY");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const SUBSCRIBER_KEY: &str = "sub-c-ecebae8e-dd60-11e6-b6b1-02ee2ddab7fe";
-const SUBSCRIBER_KEY: &str = "sub-c-ecebae8e-dd60-11e6-b6b1-02ee2ddab7fe";
+const SUBSCRIBER_KEY: &str = env!("PUBNUB_SUBSCRIBER_KEY");
🤖 Prompt for AI Agents
In exchanges/bitbank/src/socket.rs at line 4, the subscriber key is hardcoded as
a string literal, which poses a security risk. Modify the code to load this key
from an environment variable or a configuration file instead of embedding it
directly in the source code. Use appropriate Rust crates or standard library
functions to read the environment variable or configuration at runtime and
assign it to the constant or variable accordingly.

Comment thread exchanges/bitbank/src/socket.rs Outdated
Comment on lines +56 to +57
let publish_key = "my_publish_key";
let subscribe_key = "my_subscribe_key";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

テスト用のプレースホルダー認証情報

実際のテストではプレースホルダーの値ではなく、適切なモック値または環境変数を使用してください。

-        let publish_key = "my_publish_key";
-        let subscribe_key = "my_subscribe_key";
+        let publish_key = std::env::var("TEST_PUBNUB_PUBLISH_KEY").unwrap_or_else(|_| "test_publish_key".to_string());
+        let subscribe_key = std::env::var("TEST_PUBNUB_SUBSCRIBE_KEY").unwrap_or_else(|_| "test_subscribe_key".to_string());
🤖 Prompt for AI Agents
In exchanges/bitbank/src/socket.rs at lines 56 to 57, the publish_key and
subscribe_key are currently set to placeholder strings. Replace these hardcoded
placeholders with appropriate mock values for testing or retrieve the keys from
environment variables to ensure secure and flexible configuration during tests.

Comment thread exchanges/bitbank/src/message.rs
Comment on lines +217 to +223
for kline in candlestick.as_array().unwrap() {
let open = Decimal::from_str(&kline[0].as_str().unwrap()).unwrap();
let high = Decimal::from_str(&kline[1].as_str().unwrap()).unwrap();
let low = Decimal::from_str(&kline[2].as_str().unwrap()).unwrap();
let close = Decimal::from_str(&kline[3].as_str().unwrap()).unwrap();
let volume = Decimal::from_str(&kline[4].as_str().unwrap()).unwrap();
let timestamp = bitbank_timestamp_to_microsec(kline[5].as_i64().unwrap());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

unwrap()の多用によるパニックリスク

Kline変換処理で複数のunwrap()を使用しています。不正なデータ形式に対する適切なエラーハンドリングが必要です。

-        for kline in candlestick.as_array().unwrap() {
-            let open = Decimal::from_str(&kline[0].as_str().unwrap()).unwrap();
-            let high = Decimal::from_str(&kline[1].as_str().unwrap()).unwrap();
-            let low = Decimal::from_str(&kline[2].as_str().unwrap()).unwrap();
-            let close = Decimal::from_str(&kline[3].as_str().unwrap()).unwrap();
-            let volume = Decimal::from_str(&kline[4].as_str().unwrap()).unwrap();
-            let timestamp = bitbank_timestamp_to_microsec(kline[5].as_i64().unwrap());
+        let array = candlestick.as_array()
+            .ok_or_else(|| anyhow::anyhow!("candlestick is not an array"))?;
+        for kline in array {
+            let open = kline[0].as_str()
+                .ok_or_else(|| anyhow::anyhow!("open is not a string"))?;
+            let open = Decimal::from_str(open)
+                .map_err(|e| anyhow::anyhow!("Failed to parse open: {}", e))?;
+            // 同様に他のフィールドも処理

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In exchanges/bitbank/src/message.rs around lines 217 to 223, multiple unwrap()
calls are used on potentially invalid data, which can cause panics. Replace
these unwrap() calls with proper error handling by using match statements or the
? operator to propagate errors. Ensure that invalid data formats are gracefully
handled or returned as errors instead of panicking.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

♻️ Duplicate comments (6)
exchanges/bitbank/src/ws.rs (2)

32-36: 購読チャンネルがハードコードされています – 前回指摘済み


94-121: println! ではなく log 系マクロを使用してください – 既出のレビューと同内容

exchanges/bitbank/src/market.rs (1)

165-199: async_start_user_streamtodo!() が残っています

呼び出されると即時パニックします。以前のレビュー指摘と同一内容です。早急に実装するか、安全にエラーを返すようにしてください。

exchanges/bitbank/src/message.rs (3)

228-240: Decimal::from_str(...).unwrap() によるパニックリスク

パース失敗でクラッシュします。過去指摘と同様です。map_erranyhow::Error に変換してください。


345-351: デバッグ出力に println! と多重 unwrap()

本番コードでは log::debug! を使用し、unwrap() は避けてください。こちらも過去に指摘済みです。


298-305: Kline 変換での連続 unwrap()

不正データでパニックします。安全なパースに置き換えてください。以前のコメントと重複のため詳細は省略します。

🧹 Nitpick comments (13)
test/bitbank_test/test_market_basic.py (1)

25-35: テスト内 print と固定 sleep は不要 & フレーク化の温床です
CI 上では標準出力がノイズになるうえ、sleep(1)sleep(5) はネットワーク遅延で失敗したり無駄に時間を伸ばします。

  • printassert に置き換え、必要なら caplog / capfd で検証
  • 待ち合わせは market.download(...) の戻り値や状態をポーリングする方法へ

テスト実行時間短縮と安定化に繋がります。

CLAUDE.md (2)

70-72: typo: “with in” → “within”
ドキュメント上の誤字です。検索性にも影響するため修正を推奨します。

- - Recent(with in a day) historical data is stored in SQLite
+ - Recent (within a day) historical data is stored in SQLite

78-80: 英文の主語‐動詞一致の誤り
「Usually, its implement with WebSocket」→「Usually, it’s implemented with WebSocket」が自然です。

test/00_suite/test_00exchange_order.py (3)

3-3: 未使用インポートの削除
Bybit, Binance はこのテストで使用されていないため削除してください。

-from rbot import Bybit, Binance, Bitbank, ExchangeConfig
+from rbot import Bitbank, ExchangeConfig

12-17: is False/True より論理否定を使用
PEP8 E712 避けのため、以下のように書き換えを推奨します。

-    assert exchange.production is False
+    assert not exchange.production
...
-    assert exchange.enable_order_with_my_own_risk is True
+    assert exchange.enable_order_with_my_own_risk

37-38: 例外でスキップする場合は原因をログに残す
pytest.skip に加え pytest.xfaillogging を使うと、外部 API の不調とコード不具合を区別しやすくなります。

exchanges/hyperliquid/src/ws.rs (1)

50-66: add_params のパラメータ処理が堅牢でありません

params.get(1).unwrap_or(&"BTC".to_string())"l2Book" だけ渡された場合に "BTC" を借用させつつ一時オブジェクトを生成しています。
unwrap_or_else(|| "BTC".into()) などでムダな String 生成を避ける
else 分岐が無いので不正パラメータ時のエラーログを追加

を検討してください。

exchanges/hyperliquid/src/message.rs (1)

72-88: level[2] の値チェックが曖昧です

is_bid 判定を "1" 固定で行っていますが、API 仕様変更時に壊れます。
明確にドキュメント化された値 ("bid"/"ask" など) かを確認し、列挙体や関数へ抽象化すると保守性が向上します。

test/00_suite/test_bitbank_order.py (5)

15-18: True/False との比較は直接ブール値を評価
スタイル上、== True / == False は避けて直接ブール値を評価した方が読みやすく、Ruff (E712) も回避できます。

-assert(exchange.production == False)
-assert(exchange.enable_order_with_my_own_risk == True)
+assert not exchange.production
+assert exchange.enable_order_with_my_own_risk

52-56: 同上: ブール値比較の簡潔化
下記も同様に修正してください。

-assert(exchange.production == False)
-assert(exchange.enable_order_with_my_own_risk == True)
+assert not exchange.production
+assert exchange.enable_order_with_my_own_risk

78-80: 未使用変数とブール比較
config はこのテストでは参照されておらず F841 が発生します。またブール比較も簡潔化してください。

-config = BitbankConfig.BTCJPY
-assert(exchange.production == False)
+assert not exchange.production

Also applies to: 98-99


20-22: テスト出力に print を使用しない
テスト内の print はログを汚染し CI での解析を困難にします。pytest のキャプチャや logging を用いた方が適切です。

-print(order_result)
-...
-print(cancel_result)
-...
-print(order_result)
-...
-print(orders)
-...
-print(account)

Also applies to: 32-34, 57-59, 80-82, 100-103


4-40: 外部 API 依存テストにはマークやモックを検討
実際に注文を発行・取消するテストはネットワークとアカウント状態に依存し不安定になりがちです。
@pytest.mark.integration で分離するか、HTTP クライアントをモックしてユニットテスト化することを推奨します。
CI での再現性と速度が向上します。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f498f03 and e3ddcaa.

⛔ Files ignored due to path filters (4)
  • Cargo.toml is excluded by !**/*.toml
  • exchanges/example/Cargo.toml is excluded by !**/*.toml
  • exchanges/hyperliquid/Cargo.toml is excluded by !**/*.toml
  • pyproject.toml is excluded by !**/*.toml
📒 Files selected for processing (17)
  • CLAUDE.md (1 hunks)
  • exchanges/bitbank/src/config.rs (1 hunks)
  • exchanges/bitbank/src/lib.rs (1 hunks)
  • exchanges/bitbank/src/market.rs (1 hunks)
  • exchanges/bitbank/src/message.rs (2 hunks)
  • exchanges/bitbank/src/rest.rs (7 hunks)
  • exchanges/bitbank/src/socket.rs (1 hunks)
  • exchanges/bitbank/src/ws.rs (1 hunks)
  • exchanges/hyperliquid/src/lib.rs (1 hunks)
  • exchanges/hyperliquid/src/market.rs (1 hunks)
  • exchanges/hyperliquid/src/message.rs (1 hunks)
  • exchanges/hyperliquid/src/rest.rs (1 hunks)
  • exchanges/hyperliquid/src/ws.rs (1 hunks)
  • test/00_suite/test_00exchange_order.py (1 hunks)
  • test/00_suite/test_02_config.py (1 hunks)
  • test/00_suite/test_bitbank_order.py (1 hunks)
  • test/bitbank_test/test_market_basic.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • exchanges/hyperliquid/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • exchanges/bitbank/src/socket.rs
  • exchanges/bitbank/src/lib.rs
🧰 Additional context used
🧬 Code Graph Analysis (3)
exchanges/bitbank/src/config.rs (3)
exchanges/bitbank/src/market.rs (2)
  • new (47-67)
  • new (216-221)
exchanges/bitbank/src/rest.rs (1)
  • new (28-32)
modules/rbot_lib/src/common/config.rs (1)
  • open_exchange_market (53-55)
test/00_suite/test_00exchange_order.py (4)
modules/rbot_lib/src/common/config.rs (1)
  • open_exchange_market (53-55)
test/00_suite/test_bitbank_order.py (4)
  • test_limit_order_and_cancel (4-39)
  • test_market_order (41-67)
  • test_open_orders (69-87)
  • test_get_account (89-109)
exchanges/bitbank/src/market.rs (4)
  • limit_order (91-103)
  • cancel_order (118-124)
  • market_order (106-116)
  • get_open_orders (126-128)
exchanges/bitbank/src/rest.rs (2)
  • cancel_order (174-194)
  • test_get_account (544-552)
test/00_suite/test_02_config.py (5)
modules/rbot_lib/src/common/config.rs (3)
  • exchanges (58-60)
  • open (48-50)
  • open_market (80-82)
exchanges/bitbank/src/market.rs (1)
  • open_market (74-78)
exchanges/hyperliquid/src/market.rs (1)
  • open_market (101-104)
exchanges/bybit/src/market.rs (1)
  • open_market (89-93)
exchanges/binance/src/market.rs (1)
  • open_market (74-83)
🪛 Ruff (0.11.9)
test/00_suite/test_bitbank_order.py

1-1: pytest imported but unused

Remove unused import: pytest

(F401)


15-15: Avoid equality comparisons to False; use if not exchange.production: for false checks

Replace with not exchange.production

(E712)


18-18: Avoid equality comparisons to True; use if exchange.enable_order_with_my_own_risk: for truth checks

Replace with exchange.enable_order_with_my_own_risk

(E712)


52-52: Avoid equality comparisons to False; use if not exchange.production: for false checks

Replace with not exchange.production

(E712)


55-55: Avoid equality comparisons to True; use if exchange.enable_order_with_my_own_risk: for truth checks

Replace with exchange.enable_order_with_my_own_risk

(E712)


78-78: Avoid equality comparisons to False; use if not exchange.production: for false checks

Replace with not exchange.production

(E712)


98-98: Local variable config is assigned to but never used

Remove assignment to unused variable config

(F841)


99-99: Avoid equality comparisons to False; use if not exchange.production: for false checks

Replace with not exchange.production

(E712)

test/00_suite/test_00exchange_order.py

3-3: rbot.Bybit imported but unused

Remove unused import

(F401)


3-3: rbot.Binance imported but unused

Remove unused import

(F401)

test/00_suite/test_02_config.py

13-13: Found useless expression. Either assign it to a variable or remove it.

(B018)


13-13: Undefined name itewriwrite

(F821)

🪛 Pylint (3.3.7)
test/00_suite/test_02_config.py

[error] 13-13: Undefined variable 'itewriwrite'

(E0602)

🪛 LanguageTool
CLAUDE.md

[style] ~7-~7: Consider shortening or rephrasing this to strengthen your wording.
Context: ...he current state of the project. If you make changes to the codebase, please update this file a...

(MAKE_CHANGES)


[grammar] ~71-~71: Did you mean the adverb/preposition “within”?
Context: ...changed from SQLite in v0.4.0) - Recent(with in a day) historical data is stored in SQL...

(WITH_IN)


[uncategorized] ~78-~78: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ... request for exchange according to each exchanges documentation. - ws.rs implements rea...

(AI_HYDRA_LEO_APOSTROPHE_S_XS)


[uncategorized] ~79-~79: “its” (belonging to it) seems less likely than “it’s” (it is)
Context: ...me stream(public and private). Usually, its implement with WebSocket. ### Testing...

(AI_HYDRA_LEO_CPT_ITS_ITIS)


[uncategorized] ~79-~79: This verb may not be in the correct form. Consider using a different form for this context.
Context: ...tream(public and private). Usually, its implement with WebSocket. ### Testing Structure...

(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)


[uncategorized] ~83-~83: You might be missing the article “the” here.
Context: ...Structure - Test files are organized in test/ directory - Exchange-specific tes...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: linux-simple
🔇 Additional comments (2)
exchanges/bitbank/src/config.rs (1)

15-17: ```shell
#!/bin/bash
echo "Showing top 50 lines of config.rs:"
head -n50 exchanges/bitbank/src/config.rs || true

echo -e "\nLooking for pyo3 in the file:"
grep -R "pyo3" -n exchanges/bitbank/src/config.rs || true

echo -e "\nSearching for PyResult in codebase:"
grep -R "PyResult" -n .


</details>
<details>
<summary>exchanges/hyperliquid/src/rest.rs (1)</summary>

`90-105`: **ボード取得エンドポイント `/info` は適切ですか?**  

通常オーダーブックは `/l2Book` など専用エンドポイントを持つことが多く、`/info` では取得できないケースがあります。  
API ドキュメントを再確認し、不一致なら URL とペイロードを修正してください。

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment on lines +195 to +211
let stream = stream! {
loop {
match receiver.recv().await {
Ok(ReceiveMessage::Text(message)) => {
log::debug!("Hyperliquid Private WS received: {}", message);

if let Ok(ws_message) = serde_json::from_str::<HyperliquidUserWsMessage>(&message) {
match ws_message.channel.as_str() {
"user" => {
// Handle user updates (orders, fills, etc.)
// Parse and convert to MarketMessage
}
_ => {
log::debug!("Unknown private channel: {}", ws_message.channel);
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

プライベート WS でも同様にメッセージ未送出

HyperliquidPrivateWsClient 側もパース後に yield が無く、ユーザーイベントが上位へ届きません。パブリック側と同様に修正が必要です。

🤖 Prompt for AI Agents
In exchanges/hyperliquid/src/ws.rs between lines 195 and 211, the
HyperliquidPrivateWsClient does not yield parsed user events after deserializing
the WebSocket message, so these events are not propagated upstream. To fix this,
add a yield statement that outputs the converted MarketMessage after
successfully parsing and handling the "user" channel message, similar to the
public WebSocket client implementation.

Comment on lines +110 to +131
let stream = stream! {
loop {
match receiver.recv().await {
Ok(ReceiveMessage::Text(message)) => {
log::debug!("Hyperliquid WS received: {}", message);

if let Ok(ws_message) = serde_json::from_str::<HyperliquidPublicWsMessage>(&message) {
match ws_message.channel.as_str() {
"l2Book" => {
// Handle order book updates
// Parse and convert to MarketMessage
}
"trades" => {
// Handle trade updates
// Parse and convert to MarketMessage
}
_ => {
log::debug!("Unknown channel: {}", ws_message.channel);
}
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

メッセージが yield されずストリームが永遠に空になります

HyperliquidPublicWsClient::open_stream 内でパースが成功しても yield していないため、正常系の MultiMarketMessage が一切ストリームに流れません。
最低限、ws_messageMarketMessage/MultiMarketMessage に変換し yield Ok(...) する処理を追加してください。

🤖 Prompt for AI Agents
In exchanges/hyperliquid/src/ws.rs between lines 110 and 131, the stream loop
parses incoming WebSocket messages but never yields any results, causing the
stream to remain empty. To fix this, after successfully parsing ws_message and
converting it into MarketMessage or MultiMarketMessage, add a yield statement
that yields Ok(...) with the converted message so that the stream emits these
messages properly.

Comment on lines +38 to +40
fn to_string(&self) -> String {
return "".to_string();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

to_string が空文字を返しています

WsOpMessage::to_string は送信メッセージ生成で呼ばれる想定ですが、空文字列を返しており動作しません。serde_json::to_string(self)? などで正しい JSON を返してください。

🤖 Prompt for AI Agents
In exchanges/bitbank/src/ws.rs around lines 38 to 40, the to_string method
currently returns an empty string, which breaks the expected functionality of
generating a sendable message. Modify the to_string method to serialize self
into a JSON string using serde_json::to_string(self) and handle any potential
errors appropriately to return the correct JSON representation.

Comment on lines +81 to +83
let mut s = Box::pin(self.ws.open_stream().await);

stream! {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

await の不要/誤用によりコンパイルエラーの可能性

self.ws.open_stream()impl Stream を即時返す関数であれば await は不要です。

let mut s = Box::pin(self.ws.open_stream());

await を付けると StreamFuture として扱われず型不一致になります。

🤖 Prompt for AI Agents
In exchanges/bitbank/src/ws.rs around lines 81 to 83, remove the `await` after
`self.ws.open_stream()` because if `open_stream()` returns an `impl Stream`
directly, awaiting it causes a type mismatch error. Change the code to assign
`let mut s = Box::pin(self.ws.open_stream());` without `await` to fix the
compilation issue.

assert 'bybit' in exchanges
assert 'binance' in exchanges

itewriwrite

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

不要なトークン itewriwrite により構文エラー

この行は意味を持たずテスト全体を壊します。完全に削除してください。

🧰 Tools
🪛 Ruff (0.11.9)

13-13: Found useless expression. Either assign it to a variable or remove it.

(B018)


13-13: Undefined name itewriwrite

(F821)

🪛 Pylint (3.3.7)

[error] 13-13: Undefined variable 'itewriwrite'

(E0602)

🤖 Prompt for AI Agents
In test/00_suite/test_02_config.py at line 13, there is an invalid token
'itewriwrite' causing a syntax error and breaking the test. Remove this entire
line completely to fix the syntax issue and restore test functionality.

Comment on lines +270 to +274
async fn async_start_user_stream(&mut self) -> anyhow::Result<()> {
// Implementation for user stream
Ok(())
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

async_start_user_stream が未実装です

現在は空実装で何も行わず Ok(()) を返しているため、ユーザーストリームが機能しません。最低でも todo!() でパニックさせるか、実装を完了してください。

🤖 Prompt for AI Agents
In exchanges/hyperliquid/src/market.rs around lines 270 to 274, the
async_start_user_stream function is currently a no-op returning Ok(()), which
means the user stream functionality is not implemented. Replace the empty
implementation with either a todo!() macro to explicitly panic and indicate
unimplemented code, or provide a proper implementation to start the user stream
as intended.

Comment on lines +311 to +314
async fn async_start_market_stream(&mut self) -> anyhow::Result<()> {
// Implementation for market stream
Ok(())
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

async_start_market_stream も未実装

マーケットストリームも同様に空実装です。このままだと open_market_stream() から呼ばれても実際のストリーム処理が行われません。実装 or 明確な未対応エラーをお願いします。

🤖 Prompt for AI Agents
In exchanges/hyperliquid/src/market.rs around lines 311 to 314, the
async_start_market_stream function is currently a stub with no implementation,
causing open_market_stream() to not perform any actual streaming. Implement the
real market stream processing logic inside async_start_market_stream or, if not
yet supported, return a clear error indicating that this feature is
unimplemented to avoid silent failures.

Comment on lines +482 to +489
// public_ws.connect().await;

let _ = self.async_refresh_order_book().await;

self.public_handler = Some(tokio::task::spawn(async move {
let ws_stream = public_ws.open_stream().await;
let mut ws_stream = Box::pin(ws_stream);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

WebSocket 接続処理がコメントアウトされています

public_ws.connect().await がコメントアウトされたままではストリームが開始されません。open_stream() の前に必ず接続を確立してください。

🤖 Prompt for AI Agents
In exchanges/bitbank/src/market.rs around lines 482 to 489, the WebSocket
connection call public_ws.connect().await is commented out, preventing the
stream from starting. Uncomment the public_ws.connect().await line and ensure it
is awaited before calling open_stream() to properly establish the WebSocket
connection.

Comment on lines +200 to 208
let params = format!("pair={}", config.trade_symbol);

let path = "/v5/order/realtime";
let response = self.get_sign(&path, Some(&params)).await
.with_context(|| format!("open_orders error: {}{}", server.get_private_api(), path))?;

let result = Self::get_sign(&server, path, &query_string)
.await
.with_context(|| {
format!(
"open_orders: server={:?} / path={:?} / query_string={:?}",
server, path, query_string
)
})?;
log::debug!("open_orders response: {:?}", response);

log::debug!("result.body={:?}", result.body);
if result.body.is_null() {
return Ok(vec![]);
}

let response = serde_json::from_value::<BybitMultiOrderStatus>(result.body)
.with_context(|| format!("order status parse error"))?;

let mut orders: Vec<Order> = response.into();

for o in orders.iter_mut() {
o.update_balance(config);
}
let orders: Vec<BitbankOrder> = serde_json::from_value(response.data.get("orders").unwrap().clone())?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

response.data["orders"] への unwrap() は危険

open_ordersget("orders").unwrap() を呼んでいるため、API 仕様変更や失敗応答時にパニックします。ok_or_else() でエラーハンドリングし anyhow::Result に変換してください。

🤖 Prompt for AI Agents
In exchanges/bitbank/src/rest.rs around lines 200 to 208, the code uses unwrap()
on response.data["orders"], which can cause a panic if the "orders" key is
missing due to API changes or errors. Replace unwrap() with ok_or_else() to
handle the missing key gracefully by returning an appropriate anyhow::Result
error. This ensures robust error handling without panics.

@@ -0,0 +1,109 @@
import pytest

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

未使用の pytest インポートを削除してください
pytest を参照している箇所が無く、Ruff の F401 が発生します。CI を通すためにも削除を推奨します。

-import pytest
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import pytest
# (Removed unused import)
🧰 Tools
🪛 Ruff (0.11.9)

1-1: pytest imported but unused

Remove unused import: pytest

(F401)

🤖 Prompt for AI Agents
In test/00_suite/test_bitbank_order.py at line 1, the import statement for
pytest is unused and triggers a Ruff F401 warning. Remove the line importing
pytest to clean up the code and resolve the unused import issue.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
exchanges/bitbank/src/market.rs (1)

489-491: public_ws.connect().await が依然コメントアウトされたままです
過去レビュー指摘と同一内容です。接続が open_stream() 内部で行われない場合、ストリームが開始しません。必要であればコメントを外して await してください。

exchanges/bitbank/src/rest.rs (1)

207-208: unwrap() によるパニックの可能性

response.data.get("orders").unwrap() はキー欠如時にパニックします。過去にも指摘済みですが未修正です。ok_or_else(|| anyhow!("missing orders"))? などで安全にハンドリングしてください。

🧹 Nitpick comments (2)
CLAUDE.md (1)

89-100: 表記ゆれと文法ミスを修正してください

  • “Recent(with in a day)” → “Recent (within a day)”
  • “each exchanges documentation” → “each exchange’s documentation”
  • “its implement with WebSocket” → “it’s implemented with WebSocket” もしくは “it implements WebSocket”

読みやすさと正式な文法のために上記のように修正を検討してください。

exchanges/bitbank/src/rest.rs (1)

21-22: 同一定数の重複定義

BITBANK_BOARD_DEPTH は他モジュールでも定義されています。単一箇所に集約し pub use することでメンテナンス性を向上させてください。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3ddcaa and bbc55fb.

📒 Files selected for processing (4)
  • CLAUDE.md (1 hunks)
  • exchanges/bitbank/src/market.rs (1 hunks)
  • exchanges/bitbank/src/rest.rs (7 hunks)
  • modules/rbot_lib/src/common/ccxt_config.rs (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • modules/rbot_lib/src/common/ccxt_config.rs
🧰 Additional context used
🪛 LanguageTool
CLAUDE.md

[style] ~7-~7: Consider shortening or rephrasing this to strengthen your wording.
Context: ...he current state of the project. If you make changes to the codebase, please update this file a...

(MAKE_CHANGES)


[grammar] ~91-~91: Did you mean the adverb/preposition “within”?
Context: ...changed from SQLite in v0.4.0) - Recent(with in a day) historical data is stored in SQL...

(WITH_IN)


[uncategorized] ~98-~98: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ... request for exchange according to each exchanges documentation. - ws.rs implements rea...

(AI_HYDRA_LEO_APOSTROPHE_S_XS)


[uncategorized] ~99-~99: “its” (belonging to it) seems less likely than “it’s” (it is)
Context: ...me stream(public and private). Usually, its implement with WebSocket. ### Testing...

(AI_HYDRA_LEO_CPT_ITS_ITIS)


[uncategorized] ~99-~99: This verb may not be in the correct form. Consider using a different form for this context.
Context: ...tream(public and private). Usually, its implement with WebSocket. ### Testing Structure...

(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ...Structure - Test files are organized in test/ directory - Exchange-specific tes...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: linux-simple
🔇 Additional comments (2)
exchanges/bitbank/src/market.rs (1)

51-55: コメントと実装が矛盾しています

"wss://stream.bitbank.cc/…" // Bitbank doesn't have public websocket
URL をセットしている一方で「公開 WS は無い」とコメントしています。
実際に接続が成立するか確認し、不要なら空文字列にするかコメントを更新してください。

exchanges/bitbank/src/rest.rs (1)

372-376: 署名メッセージに ? を含める仕様を再確認してください

Bitbank の署名仕様は “timestamp + window + path + body(またはクエリ)” です。POST/GET で JSON ボディを送る場合に ?{json} を連結すると検証に失敗する恐れがあります。公式ドキュメントと実機テストで要確認です。

Comment on lines +497 to +503
loop {
let message = ws_stream.next().await;
if message.is_none() {
log::error!("Error in ws_stream.recv: {:?}", message);
continue;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

None 受信時にループが継続し、CPU スピンの恐れ

ws_stream.next().awaitNone を返した場合、接続は終了しています。continue ではなく break して再接続するかタスクを終了しないと無限ループになります。

🤖 Prompt for AI Agents
In exchanges/bitbank/src/market.rs around lines 497 to 503, when
ws_stream.next().await returns None, the code currently continues the loop
causing a potential infinite CPU spin. Instead of continue, replace it with a
break statement to exit the loop so that the connection can be properly handled
by reconnecting or ending the task.

- Update REST API endpoints to use correct v1 paths (/v1/user/spot/order, /v1/user/spot/cancel_order)
- Fix API base URL configuration in market.rs
- Improve error handling in order tests to gracefully handle expected API errors (20019)
- Fix WebSocket message parsing tests with proper JSON structure
- Update test assertions for BitbankAssets to match actual API response format
- Add debug logging for API signature generation
- Fix socket subscription implementation with proper PubNub client usage
- Remove path from HMAC signature message to match Bitbank API requirements

These changes ensure proper API communication and make tests more robust
by handling expected authentication/insufficient funds errors gracefully.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
exchanges/bitbank/src/rest.rs (1)

237-266: logdf_to_archivedfメソッドが未実装です。

このメソッドはtodo!()で終わっており、呼び出されるとパニックが発生します。DataFrameの変換ロジックを実装する必要があります。

コメントアウトされたコードを参考に、適切なDataFrame変換の実装を支援しますか?

♻️ Duplicate comments (7)
exchanges/bitbank/src/market.rs (2)

489-489: WebSocket接続処理がコメントアウトされています。

public_ws.connect().await がコメントアウトされたままではストリームが開始されません。open_stream() の前に必ず接続を確立してください。


497-503: None受信時にループが継続し、CPUスピンの恐れ。

ws_stream.next().awaitNone を返した場合、接続は終了しています。continue ではなく break して再接続するかタスクを終了しないと無限ループになります。

exchanges/bitbank/src/rest.rs (1)

207-207: response.data["orders"] への unwrap() は危険。

open_ordersget("orders").unwrap() を呼んでいるため、API 仕様変更や失敗応答時にパニックします。ok_or_else() でエラーハンドリングし anyhow::Result に変換してください。

exchanges/bitbank/src/message.rs (4)

221-242: 文字列からDecimalへの変換でunwrap()を使用すると、パニックが発生する可能性があります。

APIレスポンスの形式が変更された場合や不正なデータが含まれている場合、アプリケーションがクラッシュする恐れがあります。エラーハンドリングを追加することを推奨します。

同様の変更をbidsの処理にも適用してください。ただし、IntoトレイトはResultを返せないため、TryFromトレイトの使用を検討してください。


244-249: JSONデシリアライゼーションでunwrap()を使用しています。

データ形式が期待と異なる場合にパニックが発生します。TryFromトレイトの使用を検討してください。


298-304: unwrap()の多用によるパニックリスク。

Kline変換処理で複数のunwrap()を使用しています。不正なデータ形式に対する適切なエラーハンドリングが必要です。


349-350: unwrap()の使用によりパニックが発生する可能性があります。

メッセージ形式が期待と異なる場合の適切なエラーハンドリングが必要です。

🧹 Nitpick comments (2)
exchanges/bitbank/src/market.rs (2)

53-53: 矛盾するコメントを修正してください。

WebSocketのURLが設定されているにも関わらず、コメントでは"Bitbank doesn't have public websocket"と記載されています。実装と一致するようコメントを更新してください。

-            "wss://stream.bitbank.cc/socket.io/?EIO=3&transport=websocket", // Bitbank doesn't have public websocket
+            "wss://stream.bitbank.cc/socket.io/?EIO=3&transport=websocket", // Bitbank public websocket URL

539-543: Control messageのエラー処理が未実装です。

TODOコメントがあり、statusがfalseの場合のアラートやリカバリー処理が未実装です。

Control messageのエラー処理やリカバリー機能の実装を支援しますか?新しいissueを作成することも可能です。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bbc55fb and a2c05e8.

📒 Files selected for processing (4)
  • exchanges/bitbank/src/market.rs (1 hunks)
  • exchanges/bitbank/src/message.rs (2 hunks)
  • exchanges/bitbank/src/rest.rs (7 hunks)
  • exchanges/bitbank/src/socket.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • exchanges/bitbank/src/socket.rs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: linux-simple

Comment on lines +339 to 354
async fn post(&self, host: &str, path: &str, headers: Vec<(&str, &str)>, params: &str) -> anyhow::Result<BitbankRestResponse> {
let server = &self.server_config;

let response = rest_post(&server.get_private_api(), &path, headers, params)
.await
.with_context(|| format!("post_sign error {}/{}", server.get_rest_server(), path))?;
.with_context(|| format!("post error: {}{}", server.get_private_api(), path))?;

Self::parse_rest_response(response)
}
let v: BitbankRestResponse = serde_json::from_str(&response)
.with_context(|| format!("parse error in post"))?;

fn parse_rest_response(response: String) -> anyhow::Result<BybitRestResponse> {
if response == "" {
log::warn!("empty response");
let response = BybitRestResponse {
return_code: 0,
return_message: "Ok".to_string(),
return_ext_info: Value::Null,
time: NOW() / 1_000,
body: Value::Null,
};
return Ok(response);
if v.success == 0 {
return Err(anyhow!("post error: status=0, {:?}", v.data));
}

// log::debug!("rest response: {}", response);

let result = from_str::<BybitRestResponse>(&response)
.with_context(|| format!("parse error in parse_rest_response: {:?}", response))?;

ensure!(
result.is_success(),
format!("parse rest response error = {}", result.return_message)
);

return Ok(result);
Ok(v)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

postメソッドのhostパラメータが使用されていません。

メソッドシグネチャでhostパラメータを受け取っているにも関わらず、実際にはself.server_config.get_private_api()を使用しています。パラメータを使用するか、シグネチャから削除してください。

-    async fn post(&self, host: &str, path: &str, headers: Vec<(&str, &str)>, params: &str) -> anyhow::Result<BitbankRestResponse> {
-        let server = &self.server_config;
-        
-        let response = rest_post(&server.get_private_api(), &path, headers, params)
+    async fn post(&self, host: &str, path: &str, headers: Vec<(&str, &str)>, params: &str) -> anyhow::Result<BitbankRestResponse> {
+        let response = rest_post(host, &path, headers, params)

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In exchanges/bitbank/src/rest.rs around lines 339 to 354, the post method
receives a host parameter but does not use it, instead always using
self.server_config.get_private_api(). To fix this, either replace
self.server_config.get_private_api() with the host parameter in the rest_post
call to use the passed-in host, or if the host parameter is unnecessary, remove
it from the method signature to avoid unused parameters.

@yasstake yasstake merged commit 8da7aab into main Sep 1, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant