Skip to content
Go back

【GMO Coin FX API完全ガイド】5つの落とし穴と正しい実装パターン

Edit page

【GMO Coin FX API完全ガイド】5つの落とし穴と正しい実装パターン

GMO Coin FX APIを使った自動売買システムの開発で遭遇した5日間のデバッグの記録と、その過程で学んだ重要な実装パターンを共有します。


はじめに

2025年12月31日、GMO Coin FX APIを使った自動売買システムの本番運用を開始しました。しかし、初日から連続で注文が失敗。その後5日間にわたるデバッグの末、ようやく原因を特定し、2026年1月5日に完全解決しました。

この記事では、私が遭遇した5つの落とし穴と、それぞれの正しい実装パターンを詳しく解説します。

対象読者

前提知識


目次

  1. 落とし穴1: 二重JSONシリアライゼーション
  2. 落とし穴2: レスポンスデータの型不一致
  3. 落とし穴3: ポジションクローズのパラメータ設計
  4. 落とし穴4: ポジション決済の方向ロジック
  5. 落とし穴5: Pythonバイトコードキャッシュの罠
  6. まとめ: 実装チェックリスト

落とし穴1: 二重JSONシリアライゼーション

問題の症状

HTTP 404 Error (ERR-5105)
エラーメッセージ: パラメータが不正です

このERR-5105エラーが5日間、私を悩ませ続けました。APIドキュメント通りにパラメータを送信しているのに、なぜか「不正なパラメータ」と返ってきていました。

原因

APIクライアントのコード内で、JSONシリアライゼーションが二重に実行されていました。

# ❌ 間違った実装
def place_order(self, symbol: str, side: str, size: str, ...):
body = {
"symbol": symbol,
"side": side,
"size": size,
"executionType": "MARKET"
}
# 1回目のシリアライゼーション
serialized_body = json.dumps(body)

# _request()内で2回目のシリアライゼーション
return self._request("POST", "/private/v1/order", body=serialized_body)

def _request(self, method: str, path: str, body=None):
if body:
# すでにJSON文字列化されたbodyを再度シリアライゼーション
payload = json.dumps(body) # ここで二重化

結果として、GMOサーバーには以下のようなエスケープされた文字列が送信されていました。

"{\"symbol\":\"USD_JPY\",\"side\":\"BUY\",\"size\":\"10000\",\"executionType\":\"MARKET\"}"

サーバー側では、これを正しいJSONオブジェクトとして解釈できず、ERR-5105エラーを返していました。

正しい実装パターン

解決策: _request()メソッド内で型チェックを行い、辞書型の場合のみシリアライゼーションを実行します。

# ✅ 正しい実装
def place_order(self, symbol: str, side: str, size: str, ...):
body = {
"symbol": symbol,
"side": side,
"size": size,
"executionType": "MARKET"
}
# 辞書型のまま渡す
return self._request("POST", "/private/v1/order", body=body)

def _request(self, method: str, path: str, body=None):
if body:
# 型チェック: 辞書型の場合のみシリアライゼーション
if isinstance(body, dict):
payload = json.dumps(body)
elif isinstance(body, str):
payload = body # すでにJSON文字列の場合はそのまま
else:
raise TypeError(f"body must be dict or str, got {type(body)}")

専門用語解説

教訓


落とし穴2: レスポンスデータの型不一致

問題の症状

注文送信は成功するものの、レスポンスの解析で以下のエラーが発生しました。

KeyError: 'orderId'
TypeError: list indices must be integers or slices, not str

原因

GMO Coin FX APIの/private/v1/orderエンドポイントは、dataフィールドをリスト形式で返します

{
"status": 0,
"data": [
{
"orderId": "123456789",
"symbol": "USD_JPY",
"side": "BUY",
"size": "10000"
}
],
"responsetime": "2026-01-05T10:49:32.123Z"
}

しかし、私のコードはdataを辞書型として扱っていたため、エラーが発生していました。

# ❌ 間違った実装
response = self._request("POST", "/private/v1/order", body=body)
data = response.get("data")
order_id = data["orderId"] # dataがリストなのでKeyError

正しい実装パターン

解決策: レスポンスのdataフィールドがリスト型かどうかを確認し、リストの場合は最初の要素を取り出します。

# ✅ 正しい実装
response = self._request("POST", "/private/v1/order", body=body)
data = response.get("data")

# リスト型の場合は最初の要素を取得
if isinstance(data, list) and len(data) > 0:
data = data[0]

# これで辞書型として扱える
order_id = data.get("orderId")

APIドキュメントとの乖離

GMOのAPIドキュメントには、レスポンス例が以下のように記載されています。

{
"status": 0,
"data": {
"orderId": "123456789"
}
}

しかし、実際のAPIレスポンスではdataがリスト形式でした。この乖離が、デバッグを困難にしました。

専門用語解説

教訓


落とし穴3: ポジションクローズのパラメータ設計

問題の症状

ポジションを決済しようとすると、以下のエラーが発生しました。

HTTP 404 Error (ERR-5106)
エラーメッセージ: 必須パラメータが不足しています

原因

GMO Coin FX APIの/private/v1/closeOrderエンドポイントには、symbolsideパラメータが必須ですが、私の実装ではこれらを送信していませんでした。

# ❌ 間違った実装
def close_position(self, position_id: str, size: str):
body = {
"positionId": position_id,
"executionType": "MARKET",
"size": size
}
# symbolとsideが不足
return self._request("POST", "/private/v1/closeOrder", body=body)

正しい実装パターン

解決策: close_position()メソッドのシグネチャにsymbolsideを追加します。

# ✅ 正しい実装
def close_position(
self,
symbol: str, # 通貨ペア(例: "USD_JPY")
side: str, # 決済注文の方向("BUY" or "SELL")
position_id: str, # ポジションID
size: str, # 決済数量
execution_type: str = "MARKET"
):
body = {
"symbol": symbol,
"side": side,
"positionId": position_id,
"executionType": execution_type,
"size": size
}
return self._request("POST", "/private/v1/closeOrder", body=body)

APIドキュメントの読み方

GMO Coin FX APIのドキュメントには、必須パラメータが明記されています。

パラメータ必須説明
symbol通貨ペア
side注文方向(BUY/SELL)
positionId決済対象ポジションID
executionType注文タイプ(MARKET/LIMIT)
size注文数量

専門用語解説

教訓


落とし穴4: ポジション決済の方向ロジック

問題の症状

ポジション決済時に、GMOサーバーから以下のエラーが返ってきました。

ERR-5122: ポジションと決済注文の方向が一致しません

原因

FXのポジション決済では、ポジションと逆方向の注文を出す必要があります

しかし、私の実装では、ポジションと同じ方向の注文を送信していました。

# ❌ 間違った実装
position = self.get_open_positions()[0]
position_side = position["side"] # "BUY"

# BUYポジションに対してBUY注文を送信してしまう
self.close_position(
symbol=position["symbol"],
side=position_side, # ❌ ここが間違い
position_id=position["positionId"],
size=position["size"]
)

正しい実装パターン

解決策: ポジションの方向を反転させて決済注文を送信します。

# ✅ 正しい実装
position = self.get_open_positions()[0]
position_side = position["side"] # "BUY"

# ポジションの方向を反転
close_side = "SELL" if position_side == "BUY" else "BUY"

self.close_position(
symbol=position["symbol"],
side=close_side, # ✅ 反転した方向
position_id=position["positionId"],
size=position["size"]
)

FXの基礎知識: ポジションと決済

FX取引では、以下のような用語が使われます。

決済注文は、ポジションと逆方向の注文を出すことで、保有数量を相殺します。

専門用語解説

教訓


落とし穴5: Pythonバイトコードキャッシュの罠

問題の症状

上記の修正を全て適用し、Gitコミット後も、なぜか古いコードが実行されているようでした。

# コードを修正してコミット
git add execution/core/gmo_client.py
git commit -m "fix: ERR-5105 resolution"

# 実行しても、まだ古いエラーが発生
PYTHONPATH=... python main.py
# -> ERR-5105 が再発

原因

Pythonは実行時に、.pyファイルを.pycファイル(バイトコード)にコンパイルし、__pycache__/ディレクトリにキャッシュします。このキャッシュが残っていると、修正後のコードが反映されないことがあります。

_fxTradingEngine/
execution/
core/
gmo_client.py # 修正済み
__pycache__/
gmo_client.cpython-312.pyc # 古いバイトコード

正しい実装パターン

解決策1: 手動でキャッシュを削除

# プロジェクト全体のキャッシュを削除
find _fxTradingEngine -type d -name "__pycache__" -exec rm -rf {} +

# その後、再実行
PYTHONPATH=... python main.py

解決策2: 環境変数でキャッシュ生成を無効化

# 実行時にキャッシュを生成しない
PYTHONDONTWRITEBYTECODE=1 python main.py

解決策3: launchd設定でキャッシュ生成を無効化(本番環境推奨)

<!-- ~/Library/LaunchAgents/jp.systemtrade.fx.gmo.swing.plist -->
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>PYTHONDONTWRITEBYTECODE</key>
<string>1</string>
</dict>
</dict>

Pythonのキャッシュ機構

Pythonは、実行速度を向上させるため、.pyファイルをバイトコードにコンパイルし、キャッシュします。

ファイル説明
module.pyソースコード
__pycache__/module.cpython-312.pycコンパイル済みバイトコード

キャッシュの更新タイミング:

専門用語解説

教訓


まとめ: 実装チェックリスト

GMO Coin FX APIを使った自動売買システムを開発する際の、実装チェックリストを作成しました。

API統合の基本

GMO固有の実装パターン

開発・運用の注意点


おわりに

5日間のデバッグを経て、ようやくGMO Coin FX APIとの統合が成功しました。この経験から学んだことは、以下の3点です。

  1. APIドキュメントを鵜呑みにせず、実際の動作を確認する
  2. 型チェックとエラーハンドリングを徹底する
  3. 環境差異(キャッシュ、設定など)を意識する

この記事が、GMO Coin FX APIを使った自動売買システムを開発している方の助けになれば幸いです。


参考リンク



Edit page
Share this post on:

Next Post
【5日間の死闘】GMO Coin FX API ERR-5105の真犯人は二重JSON化