11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

IB API (3) オプション情報の取得

Posted at

IB API利用の準備~価格データのリクエスト
IB API (2) 仕組み~呼び出しの共通化
の続きです。
今回はSPYのオプション情報を取得します。

対象者

  • オプションを自動売買したい
  • 売買アルゴリズムのカスタマイズを自由にしたい
  • Java/C++/C#など、使い慣れた言語で書きたい
  • IB証券(LLC)の口座を持っている

前回と同様ですが、今回はオプションのみです。

処理の流れ

  1. まず対象の銘柄を決めます。今回はSPYにします
  2. 銘柄に対し、オプションの一覧を取得します
  3. 各オプションに対し、Greeksや価格を取得

2と3は同時にできそうですが、APIの仕組み上、まずは一覧を取得し(2)、詳細は一覧のそれぞれに対して要求します(3)。

関連するAPI

  • 呼び出し) reqContractDetails
  • コールバック) contractDetails / contractDetailsEnd

銘柄の詳細が得られます。
オプションでは、期日やストライクプライス・Call/Putの区別などが取得できます。

  • 呼び出し) reqMktData
  • コールバック) tickSnapshotEnd

リアルタイムで価格情報を取得します。
ただし、今回は「その時点での価格」があれば十分なので、引数で「スナップショットをください」と指定します。
スナップショットを要求した場合のみ、処理が終了した時点でtickSnapshotEndが呼ばれます。
詳細はサンプルで。

  • コールバック) tickPrice
  • コールバック) tickSize
  • コールバック) tickString
  • コールバック) tickOptionComputation

reqMktDataをオプションに対して呼び出すと、↑の4つが呼ばれます。
tickPrice, tickSize, tickStringは一般的なリアルタイムデータを、tickOptionComputationは
Greeksやオプション価格を返してくれます。

手順

まずは、銘柄詳細を得る所までです。

val contract = new Contract()
contract.m_symbol = "SPY"
contract.m_secType = "OPT"
contract.m_currency = "USD"
contract.m_exchange = "SMART"

val reqId = client.getNextValidId()
client.socket.reqContractDetails(reqId, contract)

これにより、IBClient::contractDetailsでデータが返ってきます。
ここで重要なのは、contractDetails.m_summaryです。
この中にオプション1つのリアルタイムでない情報が入っています。

例えば、
m_summary.m_expireには期日、
m_summary.m_strikeにはストライクプライス、
m_summary.m_rightには"P"か"C"が入っています。

Contract

データは↓のように処理します。

  override def contractDetailsEnd(reqId: Int): Unit =
    // complete

  override def contractDetails(reqId: Int, contractDetails: ContractDetails): Unit = {
    val contract = contractDetails.m_summary
    val date = LocalDate.parse(contract.m_expiry, DateTimeFormatter.ofPattern("yyyyMMdd"))
    // リストにcontractを保持、後でそれぞれに対しリアルタイムデータを要求する
  }

contractDetailsが何度か呼び出され、全てのオプション情報が取得できたらcontractDetailsEndが呼ばれます。

では次に、各オプションに対して価格情報などを取得します。

optionList.foreach(e =>
  client.socket.reqMktData(id, e.m_summary, "", true, null)
)

データは↓のように処理します。
今回はオプション以外のデータは不要として、捨てています。

override def tickPrice(tickerId: Int, field: Int, price: Double, canAutoExecute: Int): Unit = {}
override def tickSize(tickerId: Int, field: Int, size: Int): Unit = {}
override def tickString(tickerId: Int, tickType: Int, value: String): Unit = {}

override def tickOptionComputation(tickerId: Int, field: Int, impliedVol: Double, delta: Double, optPrice: Double, pvDividend: Double, gamma: Double, vega: Double, theta: Double, undPrice: Double): Unit = {
    val opt = // tickerIDに対応するデータ格納用変数
    opt.delta = delta
    opt.impliedVol = impliedVol
    opt.optPrice = optPrice
    opt.undPrice = undPrice
  })
}

override def tickSnapshotEnd(reqId: Int): Unit = {
  // complete
}

↑の例ではdeltaだけ保存していますが、引数にある通りGreeksは揃っています。

備考

存在するオプションの一覧を先に取得し、個別に価格を取り出すのが少しややこしいかもしれません。
とはいえ、リアルタイムで価格情報を更新するにはこうならざるを得ません。

なお、全てのオプションデータに対して価格を要求すると時間がかかるので、
私は期日や現在値±N%でフィルタリングしたりしています。

まとめ

今回はオプション価格やGreeksの取得を行いました。
サンプルは最小限なので、データを上手く格納して処理しやすい形にしましょう。

次回は自動売買らしく、オーダーを投げてみます。

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?