FX関連のAPIの中ではOANDAのものが一番使いやすそうだったので、試しに遊んでみることにしました。

公式のドキュメントはこちら↓

開発ガイド | OANDA API

基本的にこれを読むだけで大体のことは事足りそうです。

使い方

OANDA Japan 無料デモ口座開設フォーム

まずはここからデモ口座に登録し、ログイン後の画面のメニューから「MT4/API関連」→「APIアクセスの管理」に進み、Personal Acccess Tokenを発行します。

このトークンを使ってAuthorization: Bearer TOKENの形で認証を行うことで、APIが使えるようになります。

試しにアカウントのIDを取得してみました。

(* oanda_show_accounts.ml *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
open Yojson.Basic.Util

let api_token = "YOUR_API_TOKEN"

let base_url = "https://api-fxpractice.oanda.com/v1"

let accounts () : Yojson.Basic.json option Lwt.t =
  Client.get (Uri.of_string (base_url ^ "/accounts"))
             ~headers:(Header.of_list [("Authorization", "Bearer " ^ api_token)])
  >>= fun (resp, body) ->
  let status = Response.status resp in
  if (Code.code_of_status status) <> 200
  then fail_with (Code.string_of_status status)
  else Cohttp_lwt_body.to_string body >>= fun (strbody) ->
       try return (Some (Yojson.Basic.from_string strbody)) with
       | _ -> return None

let () =
  let result = Lwt_main.run (accounts ()) in
  match result with
  | None -> print_endline "parse error"
  | Some json ->
     [json]
     |> filter_member "accounts"
     |> flatten
     |> filter_member "accountId"
     |> filter_int
     |> List.iter (fun id -> print_endline (string_of_int id))

実行してみると、(今アカウントを作った所なら)デフォルトのアカウントのIDが1つ表示されるはずです。

$ ocamlfind ocamlopt -o oanda_show_accounts.native -linkpkg -package cohttp,lwt,cohttp.lwt,yojson oanda_show_accounts.ml
$ ./oanda_show_accounts.native
1234567

ほとんどコードは同じですが、取引可能な銘柄一覧を取得してみました。

(* oanda_show_instruments.ml *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
open Yojson.Basic.Util

let api_token = "YOUR_API_TOKEN"
let account_id = (さっき取得したアカウントID)

let base_url = "https://api-fxpractice.oanda.com/v1"

let accounts () : Yojson.Basic.json option Lwt.t =
  Client.get (Uri.add_query_param' (Uri.of_string (base_url ^ "/instruments"))
                                   ("accountId", string_of_int account_id))
             ~headers:(Header.of_list [("Authorization", "Bearer " ^ api_token)])
  >>= fun (resp, body) ->
  let status = Response.status resp in
  if (Code.code_of_status status) <> 200
  then fail_with (Code.string_of_status status)
  else Cohttp_lwt_body.to_string body >>= fun (strbody) ->
       try return (Some (Yojson.Basic.from_string strbody)) with
       | _ -> return None

let () =
  let result = Lwt_main.run (accounts ()) in
  match result with
  | None -> print_endline "parse error"
  | Some json ->
     [json]
     |> filter_member "instruments"
     |> flatten
     |> filter_member "instrument"
     |> filter_string
     |> List.iter print_endline

実行結果:

$ ocamlfind ocamlopt -o oanda_show_instruments.native -linkpkg -package cohttp,lwt,cohttp.lwt,yojson oanda_show_instruments.ml
$ ./oanda_show_instruments.native
AUD_CAD
AUD_CHF
AUD_HKD
AUD_JPY
AUD_NZD
AUD_SGD
AUD_USD
...

ちなみに、僕の環境ではsandboxのAPIを叩こうとしたところタイムアウトしてしまいました。他のAPIに比べて安定性がないと書かれていたので、そんなもんなのかもしれません。