🎯 cTrader Open APIでリアルタイム価格を取得!Python実践チュートリアル【コピペでOK】
🎯 cTrader Open APIでリアルタイム価格を取得!Python実践チュートリアル
この記事でできるようになること
- シンボル(通貨ペア)の一覧を取得する
- リアルタイムでBid/Askを受信する
- 価格データを使って独自の処理を行う
前回の記事でOpen APIへの接続ができるようになりましたね。今回は実際に価格データを取得していきます!
準備:前回の復習
まず、前回作った接続コードを土台にします。
from ctrader_open_api import Client, Protobuf, TcpProtocol, EndPointsfrom ctrader_open_api.messages.OpenApiCommonMessages_pb2 import *from ctrader_open_api.messages.OpenApiMessages_pb2 import *from twisted.internet import reactor
# 認証情報(あなたの値に置き換えて)CLIENT_ID = "あなたのClient ID"CLIENT_SECRET = "あなたのClient Secret"ACCESS_TOKEN = "取得したアクセストークン"ACCOUNT_ID = 12345678 # 数値で指定
# ライブorデモの選択HOST = EndPoints.PROTOBUF_LIVE_HOST # ライブ# HOST = EndPoints.PROTOBUF_DEMO_HOST # デモの場合はこちら
client = Client(HOST, EndPoints.PROTOBUF_PORT, TcpProtocol)Step 1: シンボル一覧を取得する
MQLでいう「MarketInfo」の代わり
MQLでは Symbol() や MarketInfo() で通貨ペアの情報を取得できましたよね。
Open APIでは、まずシンボルの一覧を取得して、それぞれのシンボルIDを把握する必要があります。
def getSymbols(): """シンボル一覧を取得""" request = ProtoOASymbolsListReq() request.ctidTraderAccountId = ACCOUNT_ID deferred = client.send(request) deferred.addCallback(onSymbolsList)
def onSymbolsList(result): """シンボル一覧の受信""" print(f"📋 {len(result.symbol)} 個のシンボルを取得!")
# EURUSDを探す for symbol in result.symbol: if "EURUSD" in symbol.symbolName: print(f"🔍 発見: {symbol.symbolName} (ID: {symbol.symbolId})") print(f" 小数点以下桁数: {symbol.digits}") print(f" pip位置: {symbol.pipPosition}")実行結果
📋 127 個のシンボルを取得!🔍 発見: EURUSD (ID: 1) 小数点以下桁数: 5 pip位置: 4💡 ポイント: シンボルIDは口座によって異なる場合があります。必ず自分の口座で確認してください!
Step 2: 完全版コード - シンボル取得
実際に動かせる完全なコードはこちら:
from ctrader_open_api import Client, Protobuf, TcpProtocol, EndPointsfrom ctrader_open_api.messages.OpenApiCommonMessages_pb2 import *from ctrader_open_api.messages.OpenApiMessages_pb2 import *from twisted.internet import reactor
# 設定CLIENT_ID = "あなたのClient ID"CLIENT_SECRET = "あなたのClient Secret"ACCESS_TOKEN = "取得したアクセストークン"ACCOUNT_ID = 12345678
client = Client(EndPoints.PROTOBUF_LIVE_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol)
# シンボル情報を保存する辞書symbols = {}
def onConnected(client): print("🔗 接続成功!") # アプリ認証 request = ProtoOAApplicationAuthReq() request.clientId = CLIENT_ID request.clientSecret = CLIENT_SECRET deferred = client.send(request) deferred.addCallback(onAppAuth)
def onAppAuth(result): print("✅ アプリ認証完了") # アカウント認証 request = ProtoOAAccountAuthReq() request.ctidTraderAccountId = ACCOUNT_ID request.accessToken = ACCESS_TOKEN deferred = client.send(request) deferred.addCallback(onAccountAuth)
def onAccountAuth(result): print("✅ アカウント認証完了") # シンボル一覧を取得 request = ProtoOASymbolsListReq() request.ctidTraderAccountId = ACCOUNT_ID deferred = client.send(request) deferred.addCallback(onSymbolsList)
def onSymbolsList(result): print(f"\n📋 {len(result.symbol)} 個のシンボルを取得!\n")
# 主要通貨ペアを表示 major_pairs = ["EURUSD", "USDJPY", "GBPUSD", "AUDUSD", "XAUUSD"]
for symbol in result.symbol: # 辞書に保存 symbols[symbol.symbolName] = { "id": symbol.symbolId, "digits": symbol.digits, "pipPosition": symbol.pipPosition }
# 主要ペアのみ表示 if symbol.symbolName in major_pairs: print(f"💰 {symbol.symbolName}") print(f" ID: {symbol.symbolId}") print(f" 桁数: {symbol.digits}") print(f" pip位置: {symbol.pipPosition}") print()
reactor.stop()
def onError(failure): print(f"❌ エラー: {failure}") reactor.stop()
# コールバック設定client.setConnectedCallback(onConnected)client.setDisconnectedCallback(lambda client, reason: print(f"切断: {reason}"))client.startService()reactor.run()Step 3: リアルタイム価格を受信する
いよいよ本番!リアルタイムでBid/Askを受信します。
サブスクライブの仕組み
MQLでは Bid や Ask 変数でいつでも価格にアクセスできましたが、Open APIでは:
- 「この通貨ペアの価格を送ってね」とサブスクライブ(購読)
- 価格が変わるたびにイベントが飛んでくる
- そのイベントを受け取って処理
というプッシュ型の仕組みです。
サブスクライブのコード
def subscribeSpots(symbolId): """リアルタイム価格をサブスクライブ""" request = ProtoOASubscribeSpotsReq() request.ctidTraderAccountId = ACCOUNT_ID request.symbolId.append(symbolId) deferred = client.send(request) deferred.addCallback(lambda r: print(f"✅ シンボルID {symbolId} をサブスクライブ開始!"))価格イベントを受信
def onMessageReceived(client, message): """受信したメッセージを処理""" if message.payloadType == ProtoOASpotEvent().payloadType: # 価格データを取得 spot = Protobuf.extract(message)
# 価格を計算(整数値 ÷ 100000) bid = spot.bid / 100000 if spot.HasField('bid') else None ask = spot.ask / 100000 if spot.HasField('ask') else None
print(f"💹 シンボルID {spot.symbolId}: Bid={bid}, Ask={ask}")💡 重要: Open APIの価格は整数値で送られてきます!
例えば EURUSD の Bid が 110523 なら、実際の価格は 1.10523 です(100000で割る)。
Step 4: 完全版コード - リアルタイム価格取得
全部組み合わせた完全版コードです。コピペでそのまま動きます!
from ctrader_open_api import Client, Protobuf, TcpProtocol, EndPointsfrom ctrader_open_api.messages.OpenApiCommonMessages_pb2 import *from ctrader_open_api.messages.OpenApiMessages_pb2 import *from twisted.internet import reactorimport time
# ============================================# 設定(ここを自分の値に置き換えて!)# ============================================CLIENT_ID = "あなたのClient ID"CLIENT_SECRET = "あなたのClient Secret"ACCESS_TOKEN = "取得したアクセストークン"ACCOUNT_ID = 12345678 # 数値で
# 価格を取得したい通貨ペアTARGET_SYMBOLS = ["EURUSD", "USDJPY", "XAUUSD"]
# ============================================
client = Client(EndPoints.PROTOBUF_LIVE_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol)
# データ保存用symbols_info = {}current_prices = {}
def onConnected(client): print("=" * 50) print("🔗 cTrader Open APIに接続しました!") print("=" * 50)
request = ProtoOAApplicationAuthReq() request.clientId = CLIENT_ID request.clientSecret = CLIENT_SECRET deferred = client.send(request) deferred.addCallback(onAppAuth)
def onAppAuth(result): print("✅ アプリケーション認証完了")
request = ProtoOAAccountAuthReq() request.ctidTraderAccountId = ACCOUNT_ID request.accessToken = ACCESS_TOKEN deferred = client.send(request) deferred.addCallback(onAccountAuth)
def onAccountAuth(result): print("✅ アカウント認証完了") print("\n📋 シンボル一覧を取得中...")
request = ProtoOASymbolsListReq() request.ctidTraderAccountId = ACCOUNT_ID deferred = client.send(request) deferred.addCallback(onSymbolsList)
def onSymbolsList(result): print(f"✅ {len(result.symbol)} 個のシンボルを取得\n")
# ターゲットシンボルのIDを取得 subscribe_ids = [] for symbol in result.symbol: symbols_info[symbol.symbolId] = { "name": symbol.symbolName, "digits": symbol.digits }
if symbol.symbolName in TARGET_SYMBOLS: subscribe_ids.append(symbol.symbolId) print(f" 🎯 {symbol.symbolName} (ID: {symbol.symbolId})")
print("\n" + "=" * 50) print("📡 リアルタイム価格のサブスクライブを開始...") print("=" * 50 + "\n")
# スポット価格をサブスクライブ request = ProtoOASubscribeSpotsReq() request.ctidTraderAccountId = ACCOUNT_ID for sid in subscribe_ids: request.symbolId.append(sid) deferred = client.send(request) deferred.addCallback(lambda r: print("✅ サブスクライブ開始!価格が更新されると表示されます\n"))
def onMessageReceived(client, message): """リアルタイムで受信するメッセージを処理""" # SpotEvent(価格更新)を処理 if message.payloadType == 2131: # ProtoOASpotEvent spot = Protobuf.extract(message)
symbol_id = spot.symbolId symbol_name = symbols_info.get(symbol_id, {}).get("name", f"ID:{symbol_id}") digits = symbols_info.get(symbol_id, {}).get("digits", 5)
# 価格を計算 divisor = 10 ** digits bid = spot.bid / divisor if spot.HasField('bid') else current_prices.get(symbol_id, {}).get('bid') ask = spot.ask / divisor if spot.HasField('ask') else current_prices.get(symbol_id, {}).get('ask')
# 保存 current_prices[symbol_id] = {"bid": bid, "ask": ask}
# 表示 timestamp = time.strftime("%H:%M:%S") spread = (ask - bid) * (10 ** (digits - 1)) if bid and ask else 0
print(f"[{timestamp}] 💹 {symbol_name}") print(f" Bid: {bid:.{digits}f} Ask: {ask:.{digits}f} Spread: {spread:.1f}pips") print()
def onDisconnected(client, reason): print(f"\n❌ 切断されました: {reason}") reactor.stop()
# コールバック設定client.setConnectedCallback(onConnected)client.setDisconnectedCallback(onDisconnected)client.setMessageReceivedCallback(onMessageReceived)
# 起動print("\n🚀 cTrader Open API リアルタイム価格取得ツール")print(" Ctrl+C で終了\n")client.startService()reactor.run()実行結果
🚀 cTrader Open API リアルタイム価格取得ツール Ctrl+C で終了
==================================================🔗 cTrader Open APIに接続しました!==================================================✅ アプリケーション認証完了✅ アカウント認証完了
📋 シンボル一覧を取得中...✅ 127 個のシンボルを取得
🎯 EURUSD (ID: 1) 🎯 USDJPY (ID: 2) 🎯 XAUUSD (ID: 41)
==================================================📡 リアルタイム価格のサブスクライブを開始...==================================================
✅ サブスクライブ開始!価格が更新されると表示されます
[09:15:23] 💹 EURUSD Bid: 1.10523 Ask: 1.10525 Spread: 0.2pips
[09:15:23] 💹 USDJPY Bid: 149.852 Ask: 149.855 Spread: 0.3pips
[09:15:24] 💹 XAUUSD Bid: 2654.35 Ask: 2654.85 Spread: 5.0pipsリアルタイムで価格が流れてきます!😆
応用:価格データを使って条件判定
取得した価格を使って、何かアクションを起こしてみましょう。
例:スプレッドが広がったら警告
def checkSpread(symbol_name, bid, ask, digits): """スプレッドをチェックして警告""" spread_pips = (ask - bid) * (10 ** (digits - 1))
# 通貨ペアごとの閾値 thresholds = { "EURUSD": 1.0, "USDJPY": 1.0, "XAUUSD": 10.0 }
threshold = thresholds.get(symbol_name, 2.0)
if spread_pips > threshold: print(f"⚠️ 警告: {symbol_name} のスプレッドが {spread_pips:.1f}pips に拡大!") # ここでSlack通知やメール送信などを追加例:価格がラウンドナンバーに接近
def checkRoundNumber(symbol_name, bid, digits): """ラウンドナンバーへの接近をチェック""" if symbol_name == "USDJPY": # 150.000 に接近したら通知 if 149.95 < bid < 150.05: print(f"🎯 {symbol_name} が 150.000 に接近中! 現在: {bid}")
elif symbol_name == "EURUSD": # 1.10000 に接近したら通知 if 1.0995 < bid < 1.1005: print(f"🎯 {symbol_name} が 1.10000 に接近中! 現在: {bid}")トラブルシューティング
Q: 価格が表示されない
A: 以下を確認してください:
-
シンボルIDは正しい?
- 口座によってIDが違います
onSymbolsListで確認
-
市場は開いている?
- 週末や祝日は価格更新がありません
-
サブスクライブは成功した?
ProtoOASubscribeSpotsResのエラーをチェック
Q: 価格が変な値になる
A: 桁数(digits)の扱いを確認:
# 正しい計算divisor = 10 ** digitsactual_price = raw_price / divisor
# 例:EURUSD (digits=5) で raw_price=110523# actual_price = 110523 / 100000 = 1.10523 ✅Q: 「too many requests」エラー
A: サブスクライブは一度だけで十分です。ループで何度も送らないでください。
MQLとの比較:価格取得
| やりたいこと | MQL | Open API (Python) |
|---|---|---|
| 現在の Bid | Bid | ProtoOASpotEvent を受信 |
| 現在の Ask | Ask | ProtoOASpotEvent を受信 |
| シンボル情報 | MarketInfo() | ProtoOASymbolsListReq |
| 価格更新検知 | OnTick() | onMessageReceived() |
MQLの方がシンプルに見えますが、Open APIはより柔軟です。複数シンボルを一度にサブスクライブしたり、必要なものだけ受信したりできます。
次のステップ
この記事で学んだこと:
- ✅ シンボル一覧の取得方法
- ✅ リアルタイム価格のサブスクライブ
- ✅ 価格データの正しい変換方法
- ✅ 応用例(スプレッド監視など)
次の記事では、ついに注文を出す方法を解説します!Market Order、Limit Order、SL/TP設定まで、実際にトレードできるようになります。
まとめ
リアルタイム価格が取得できるようになりましたね!🎉
これができれば:
- 価格アラートシステム
- スプレッド監視ツール
- ティックデータの収集・分析
- 独自インジケーターの計算
など、いろいろなことができるようになります。
MQLでは「OnTick()の中でBid/Askを見る」だけでしたが、Open APIでは外部から自由に価格を監視できます。この自由度こそがOpen APIの真骨頂です!
次回は、いよいよ注文を出しましょう! 🚀
参考リンク
🎁おすすめツール・サービス
※上記リンクにはプロモーション(広告)が含まれています
量子相場謀略|ホソノP
ブログでは書けない本音のトレード戦略とEA開発の裏側を公開。 データに基づいた検証で、再現性のある手法だけをお届けします。