Web Lukes
📄

⚠️【非推奨】FIX API完全版①|2セッション構成→ Python cBotを使おう

公開日: 2026/1/8

🚨 重要:FIX APIは非推奨です

この記事で紹介しているFIX APIは、以下の理由から非推奨です:

  • 😱 17個のハマりポイントがあり、ドキュメントに書いてない罠が多すぎる
  • 💀 実装に1週間以上かかる(Python cBotなら数時間)
  • 🤯 800行以上のコードが必要(Python cBotなら数十行)
  • ❌ コントラクトサイズ等の情報が取得できない

🐍 代わりにPython cBotを使いましょう!

cTrader 5.4以降、ネイティブPythonサポートが追加されました。

👉 Python cBot入門ガイド - 1行で注文できる世界へ

👉 cTrader 5.4 Python完全ガイド - 環境構築から実践まで


以下の内容は参考資料として残しています。FIX APIをどうしても使いたい方のみお読みください。


【参考】FIX API完全版①|2セッション構成とパスワードの真実

この記事で解決すること

  • 「ログオンしても無応答」 → セッション構成の理解
  • 「RET_INVALID_DATA」 → パスワードの種類の理解
  • 「価格データが取れない」 → TRADE/QUOTE分離の理解

ライブ口座(Fundora)で全て検証済みの情報です。


🎯 cTrader FIX API の全体像

FIX APIとは

FIX(Financial Information eXchange)は、金融業界の標準プロトコル。

  • 高速: 機関投資家レベルの低レイテンシ
  • 信頼性: 業界標準で20年以上の実績
  • シンプル: テキストベースのプロトコル

cTraderはFIX 4.4をベースに独自拡張を加えている。


🚨 最重要: 2セッション構成

cTraderは2つのセッションが完全分離

Code
┌─────────────────────────────────────────────────────────┐
│ cTrader FIX API │
├─────────────────────────┬───────────────────────────────┤
│ TRADEセッション │ QUOTEセッション │
│ (Port 5212) │ (Port 5211) │
├─────────────────────────┼───────────────────────────────┤
│ ・新規注文 │ ・Bid/Ask価格取得 │
│ ・決済 │ ・マーケットデータ購読 │
│ ・ポジション照会 │ │
│ ・オーダー照会 │ │
│ ・シンボル情報取得 │ │
└─────────────────────────┴───────────────────────────────┘

同一ホストでもポートが違う

Python
# 例: Fundoraの場合
HOST = "live-uk-eqx-01.p.c-trader.com"
TRADE_PORT = 5212 # 注文・ポジション系
QUOTE_PORT = 5211 # 価格データ系

なぜ分離されているのか

理由説明
負荷分散価格データは高頻度(毎秒数十〜数百回)、注文は低頻度
セキュリティ注文系は厳格な認証、価格系は読み取り専用
信頼性片方が落ちても、もう片方は稼働継続
HFT対応価格データだけ超高速に取得する用途に対応

❌ よくある間違い

Python
# ❌ 1つの接続で全部やろうとする
sock = connect(HOST, TRADE_PORT)
send_logon(sock)
send_market_data_request(sock) # ← 動かない!
# ✅ 2つの接続を別々に管理
trade_sock = connect(HOST, TRADE_PORT)
quote_sock = connect(HOST, QUOTE_PORT)
send_logon(trade_sock, "TRADE")
send_logon(quote_sock, "QUOTE")

🔑 最重要: 2種類のパスワード

cTraderには2つのパスワードがある

パスワード用途FIX APIで使えるか
CTIDパスワードcTraderアプリのログイン❌ 使えない
FIXパスワードFIX API専用✅ これを使う

CTIDパスワードを使うとどうなるか

Code
→ 送信: Logon (35=A)
← 受信: Logout (35=5) with 58=RET_INVALID_DATA
「パスワード合ってるのに!」→ 違うパスワードを使ってる

これがFIX APIで一番最初にハマるポイント。

FIXパスワードの設定方法

  1. cTrader Web版にログイン

    • https://ct.○○○.com/ (ブローカーのcTrader Web)
  2. 設定 → FIX APIを開く

  3. FIX API専用パスワードを設定

    • CTIDパスワードとは別のものを設定
  4. 接続情報を確認

    • ホスト名
    • ポート番号
    • SenderCompID(通常は live.broker.口座番号 形式)

認証情報の構成

Python
# 環境変数または設定ファイルから読み込む
FIX_HOST = "live-uk-eqx-01.p.c-trader.com"
FIX_TRADE_PORT = 5212
FIX_QUOTE_PORT = 5211
FIX_SENDER_COMP_ID = "live.fundoratrading.5006639" # 口座固有
FIX_PASSWORD = "your_fix_specific_password" # FIX専用!
FIX_TRADER_LOGIN = "5006639" # 口座番号

🔌 SSL接続の実装

基本的なSSL接続コード

Python
import socket
import ssl
def connect_session(host: str, port: int, session_type: str) -> ssl.SSLSocket:
"""
SSL接続を確立
Args:
host: 接続先ホスト
port: ポート番号(TRADE=5212, QUOTE=5211)
session_type: "TRADE" or "QUOTE"
Returns:
ssl.SSLSocket: 接続済みソケット
"""
print(f"🔗 {session_type}セッション {host}:{port} に接続中...")
# 生ソケット作成
raw_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
raw_sock.settimeout(10) # 接続タイムアウト
# SSL/TLSでラップ
context = ssl.create_default_context()
# cTraderは正規証明書を使用、検証無効化は不要
# context.check_hostname = False # ❌ 本番では使わない
# context.verify_mode = ssl.CERT_NONE # ❌ 本番では使わない
wrapped_sock = context.wrap_socket(raw_sock, server_hostname=host)
wrapped_sock.connect((host, port))
wrapped_sock.settimeout(1) # 受信タイムアウト(短め)
print(f"✅ {session_type}セッション SSL接続完了")
return wrapped_sock

両セッションへの接続

Python
# TRADE接続
trade_sock = connect_session(FIX_HOST, FIX_TRADE_PORT, "TRADE")
# QUOTE接続
quote_sock = connect_session(FIX_HOST, FIX_QUOTE_PORT, "QUOTE")

📝 ログオンメッセージの構成

必須フィールド

Code
┌─────┬──────────────────┬─────────────────────────────────┐
│ Tag │ 名称 │ 値の例 │
├─────┼──────────────────┼─────────────────────────────────┤
│ 35 │ MsgType │ A(ログオン) │
│ 49 │ SenderCompID │ live.fundoratrading.5006639 │
│ 56 │ TargetCompID │ cServer │
│ 57 │ TargetSubID │ TRADE または QUOTE ← 超重要! │
│ 50 │ SenderSubID │ TRADE または QUOTE │
│ 34 │ MsgSeqNum │ 1 │
│ 52 │ SendingTime │ 20260107-14:00:00 │
│ 98 │ EncryptMethod │ 0(暗号化なし) │
│ 108 │ HeartBtInt │ 30 │
│ 141 │ ResetSeqNumFlag │ Y │
│ 553 │ Username │ 5006639(口座番号) │
│ 554 │ Password │ FIX専用パスワード │
└─────┴──────────────────┴─────────────────────────────────┘

超重要: TargetSubID(タグ57)

Python
# ❌ TargetSubIDなし → 無応答
f"49={SENDER}{SOH}56={TARGET}{SOH}34=1{SOH}..."
# ✅ TargetSubIDあり → 動く
f"49={SENDER}{SOH}56={TARGET}{SOH}57=TRADE{SOH}34=1{SOH}..."

タグ57がないと、サーバーはどのセッションかわからず無視する。

Python実装

Python
SOH = "\x01"
def build_logon_message(session_type: str, seq_num: int) -> str:
"""
ログオンメッセージを構築
Args:
session_type: "TRADE" or "QUOTE"
seq_num: シーケンス番号
Returns:
str: FIXメッセージ文字列
"""
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H:%M:%S.%f")[:-3]
body = (
f"35=A{SOH}"
f"49={FIX_SENDER_COMP_ID}{SOH}"
f"56=cServer{SOH}"
f"57={session_type}{SOH}" # ← 重要!
f"50={session_type}{SOH}"
f"34={seq_num}{SOH}"
f"52={timestamp}{SOH}"
f"98=0{SOH}" # 暗号化なし
f"108=30{SOH}" # ハートビート30秒
f"141=Y{SOH}" # シーケンスリセット
f"553={FIX_TRADER_LOGIN}{SOH}"
f"554={FIX_PASSWORD}{SOH}"
)
# ヘッダー(8=, 9=)
body_length = len(body.encode('utf-8'))
header = f"8=FIX.4.4{SOH}9={body_length}{SOH}"
# チェックサム計算
msg_without_checksum = header + body
checksum = sum(ord(c) for c in msg_without_checksum) % 256
checksum_str = f"10={checksum:03d}{SOH}"
return msg_without_checksum + checksum_str

📨 メッセージタイプ一覧

システムメッセージ

MsgType名称方向説明
ALogon送受信セッション開始
5Logout送受信セッション終了
0Heartbeat送受信生存確認
1TestRequest受信ハートビート要求
3Reject受信セッションレベル拒否

アプリケーションメッセージ(TRADE)

MsgType名称方向説明
DNewOrderSingle送信新規注文
FOrderCancelRequest送信注文キャンセル
HOrderStatusRequest送信注文状態照会
AFOrderMassStatusRequest送信全注文状態照会
8ExecutionReport受信約定レポート
9OrderCancelReject受信キャンセル拒否
ANRequestForPositions送信ポジション照会
APPositionReport受信ポジション情報
AORequestForPositionsAck受信ポジション照会応答
xSecurityListRequest送信シンボル情報要求
ySecurityList受信シンボル情報
jBusinessReject受信ビジネスロジック拒否

アプリケーションメッセージ(QUOTE)

MsgType名称方向説明
VMarketDataRequest送信価格データ購読
WMarketDataSnapshot受信価格スナップショット
XMarketDataIncremental受信価格更新
YMarketDataReject受信価格データ拒否

🆔 シンボルIDについて

重要: シンボルは文字列ではなく数値ID

Python
# ❌ 文字列(動かない)
f"55=XAUUSD{SOH}"
# ✅ 数値ID
f"55=41{SOH}"

シンボルIDの確認方法

  1. cTrader Web版で対象シンボルを開く
  2. 詳細/情報タブを表示
  3. **「FIX通貨ペアID」**を確認

既知のシンボルID例(Fundora)

シンボルID説明
XAUUSD41ゴールド/ドル
EURUSD1ユーロ/ドル
GBPUSD2ポンド/ドル
USDJPY3ドル/円

⚠️ ブローカーによってIDは異なる!必ず確認すること。


💡 FIX API の制限事項

FIX APIでできないこと

  1. 口座情報の取得

    • 残高、証拠金、レバレッジは取得不可
    • → Open APIを併用する必要あり
  2. ヒストリカルデータの取得

    • 過去の価格データは取得不可
    • FIXは「最速の接続」に特化
  3. コントラクトサイズの取得

    • 商品のコントラクトサイズは取得不可
    • → 事前に調べておく必要あり
  4. 全シンボル一覧の取得

    • SecurityListRequestType=4(全シンボル)は非対応
    • → 個別シンボルのみ取得可能

cTrader独自の制限

Python
# 標準FIX 4.4で使えるはずのタグが使えない
# ❌ ポジション照会で使えないタグ
f"1={ACCOUNT}{SOH}" # Account
f"263=1{SOH}" # SubscriptionRequestType
f"453=1{SOH}" # NoPartyIDs
f"724=0{SOH}" # PosReqType
# ✅ cTraderではタグ710だけ
f"710={pos_req_id}{SOH}"

🔄 接続フロー

完全な接続手順

Code
1. TRADEソケット作成(SSL)
└─> 5212ポートに接続
2. TRADEログオン送信
└─> 35=A with 57=TRADE
3. TRADEログオン応答待ち
└─> 35=A が返ってきたら成功
4. QUOTEソケット作成(SSL)
└─> 5211ポートに接続
5. QUOTEログオン送信
└─> 35=A with 57=QUOTE
6. QUOTEログオン応答待ち
└─> 35=A が返ってきたら成功
7. 準備完了
└─> TRADE: 注文・ポジション操作可能
└─> QUOTE: 価格データ取得可能

受信スレッドの構成

Code
メインスレッド
├── スケジュール管理
├── 注文判断ロジック
│
├── TRADE受信スレッド
│ └── 約定・ポジション・エラー受信
│
└── QUOTE受信スレッド
└── 価格データ受信

🏥 ハートビート対応

30秒ごとにハートビートを送信

サーバーは30秒以上無通信だと切断する可能性がある。

Python
def send_heartbeat(sock, session_type: str, test_req_id: str = ""):
"""ハートビート送信"""
body = f"35=0{SOH}..."
if test_req_id:
body += f"112={test_req_id}{SOH}" # TestRequest応答時
# ... メッセージ構築して送信

TestRequest(35=1)への応答

サーバーからTestRequestが来たら、即座にハートビートで応答:

Python
def handle_message(msg: str, sock, session_type: str):
fields = parse_fix_message(msg)
msg_type = fields.get("35", "")
if msg_type == "1": # TestRequest
test_req_id = fields.get("112", "")
send_heartbeat(sock, session_type, test_req_id)

❌ よくあるエラーと対処

RET_INVALID_DATA

Code
58=RET_INVALID_DATA

原因: CTIDパスワードを使用している 対処: cTrader Web → 設定 → FIX APIでFIX専用パスワードを設定

Invalid tag number

Code
58=Invalid tag number, field=1
58=Invalid tag number, field=724

原因: cTrader非対応のFIXタグを使用 対処: 公式ドキュメントで対応タグを確認

無応答

原因:

  1. TargetSubID(57)の欠落
  2. ボディ長(9)の計算ミス
  3. チェックサム(10)の計算ミス

対処: ログを出力してメッセージ内容を確認


📝 まとめ

覚えておくべき3つのこと

  1. TRADEとQUOTEは完全に別セッション

    • ポート5212: 注文・ポジション
    • ポート5211: 価格データ
  2. パスワードは2種類ある

    • CTIDパスワード: アプリ用(FIX APIでは使えない)
    • FIXパスワード: FIX API専用(これを使う)
  3. TargetSubID(57)は必須

    • TRADEセッション: 57=TRADE
    • QUOTEセッション: 57=QUOTE

次のステップ

この記事では接続の基礎を解説しました。次の記事では:


📚 参考リンク


検証環境: Fundora (cTrader) ライブ口座 最終更新: 2026-01-08

🎁おすすめツール・サービス

FX自動売買VPSなら50%OFF

キャンペーンで月1,790円〜。MT4/MT5プリインストール済み、自動復旧機能付き。14日間無料お試し。

シンクラウドデスクトップ for FX
ゴトー日EAを探しているならソースコード付

4年で資金4.7倍のバックテスト実績。ソースコード付きで自由にカスタマイズ可能。

ゴトー日EA Ultimate版(3,980円)

※上記リンクにはプロモーション(広告)が含まれています

🔮
MEMBERSHIP

量子相場謀略|ホソノP

ブログでは書けない本音のトレード戦略とEA開発の裏側を公開。 データに基づいた検証で、再現性のある手法だけをお届けします。

✓EAソースコード公開
✓バックテスト生データ共有
✓リアルタイム相場分析
✓メンバー限定記事
メンバーシップに参加する※ noteアカウントで簡単登録

📚あわせて読みたい

📄

🎊 cTrader 5.4でPython cBotが書ける!ネイティブPythonサポート完全ガイド【Open APIとの違いも解説】

cTrader 5.4で追加されたネイティブPythonサポートを徹底解説。cBot、インジケーターをPythonで作成する方法、Open APIとの違い、MQL経験者のための移行ガイド。

trading2026/1/7
📄

😤「MQLは書けるのにcTraderで自動売買できない!」そんなあなたへ贈る cTrader Open API × Python 入門ガイド

MQL経験者がcTrader Open APIとPythonで自動売買を始めるための完全入門ガイド。環境構築からアプリ登録、認証の仕組みまで丁寧に解説します。

trading2026/1/7
📄

🔥 cTrader Open APIで自動売買!Pythonで注文を出す完全ガイド【Market/Limit/SL/TP対応】

cTrader Open APIとPythonで実際に注文を出す方法を完全解説。成行注文、指値注文、SL/TP設定、ポジション決済まで、コピペで動くサンプルコード付き。

trading2026/1/7
📄

🎯 cTrader Open APIでリアルタイム価格を取得!Python実践チュートリアル【コピペでOK】

cTrader Open APIとPythonでリアルタイムの為替レートを取得する方法を解説。シンボル一覧取得からティックデータの受信まで、実際に動くコードで学べます。

trading2026/1/7
📄

⚠️【非推奨】FIX API入門④|17個のハマりポイント→ Python cBotを使おう

【非推奨】FIX APIは17個のハマりポイントがあり初心者には推奨しません。代わりにPython cBotを使いましょう。この記事は参考資料として残しています。

fx2026/1/8
📄

⚠️【非推奨】FIX API完全版⑤|全機能クラス→ Python cBotを使おう

【非推奨】FIX APIは17個のハマりポイントがあり初心者には推奨しません。代わりにPython cBotを使いましょう。この記事は参考資料として残しています。

ctrader2026/1/8