IB API利用の準備~価格データのリクエスト
IB API (2) 仕組み~呼び出しの共通化
の続きです。
今回はSPYのオプション情報を取得します。
対象者
- オプションを自動売買したい
- 売買アルゴリズムのカスタマイズを自由にしたい
- Java/C++/C#など、使い慣れた言語で書きたい
- IB証券(LLC)の口座を持っている
前回と同様ですが、今回はオプションのみです。
処理の流れ
- まず対象の銘柄を決めます。今回はSPYにします
- 銘柄に対し、オプションの一覧を取得します
- 各オプションに対し、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"が入っています。
データは↓のように処理します。
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の取得を行いました。
サンプルは最小限なので、データを上手く格納して処理しやすい形にしましょう。
次回は自動売買らしく、オーダーを投げてみます。