FIX プロトコルについてまとめてみた

# FIXの概念

前置き:
今回業務でFIXについて機会があったものの、詳しく書いてある記事が少なすぎました。
OANDAの仕様を参考にしたんでOANDAの仕様なのかFIXの仕様なのかなるべく読み取って書いていくつもりですが
もしかしたごっちゃになってる部分もあるかもしれないのでお見知り置きを…分かる方は是非コメント・ご指摘を…

## FIXとは？
FIX (Financial Information eXchange: 金融情報交換)プロトコルは
財務データや銀行取引に関連するメッセージを電子的にやりとりするための一連のメッセージ仕様。
世界中の銀行やブローカー、取引所、機関投資家、情報技術(IT)プロパイダの協力によって開発され
メッセージ使用の標準として世界的に認められている……

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289294/6b9b101b-2936-a789-883a-2b719666b9c9.png)


で？つまり？
→金融の情報（Financial Information eXchange)を電子的にやり取りするために
プロトコル（取り決め）を制定したものですよってこと

## FIXの仕組み
クライアントはFIXメッセージをサーバーに送信(アウトバウンド)
その後、サーバーからクライアントにメッセージを返す(インバウンド)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289294/c12bbaf6-4fd5-b6dd-2c78-527df0888fd1.png)


FIX セッションは、Logon メッセージで開始されなければならない
ログオンメッセージって？
→(https://www.onixs.biz/fix-dictionary/4.3/msgType_A_65.html)

### FIXメッセージとは？
FIXメッセージは、いくつかのフィールドから形成される。

FIXメッセージ全体の構成　
→ 「ヘッダー（全メッセージ共通）＋ボディ（メッセージタイプによって違う）＋トレーラー（全メッセージ共通）」

FIX.4.4まで、ヘッダーには3つのフィールドが含まれていた
8（BeginString）、9（BodyLength）、および35（MsgType）タグ

FIXT.1.1 / FIX.5.0から、ヘッダーには5つの必須フィールドと1つのオプションフィールドが含まれている
8（BeginString）、9（BodyLength）、35（MsgType）、49（SenderCompID）、56（TargetCompID）および1128（ApplVerID-存在する場合は6番目の位置にある必要がある） ）

各フィールドは、区切り文字（SOH）によって次のフィールドから分離された
タグと値（ASCIIコード→１６進数の文字コード）のペア
・タグ・・・フィールドの意味を示す整数
・値・・・特定のタグの特定の意味を保持するバイトの配列

つまり「タグ＝値」になる

タグの例）
48（セキュリティを識別する文字列、securityID）
22（使用されている識別子クラスを示す整数、DSource）

タグの一覧っぽいもの(FIX4.2)を見つけたのでリンク→[タグ一覧](https://www.onixs.biz/fix-dictionary/4.2/fields_by_tag.html)

*メッセージの本文の内容→「MsgType」ヘッダーで定義された（タグ35）メッセージタイプによって指定される
*メッセージの最後のフィールド→タグ10、FIXメッセージチェックサム。常に3桁の数字。これは必須ぽい

↓OANDA仕様書のログオンメッセージの一例
```
+-HEADER 
| 8 BeginString = FIX.4.4 
| 35 MsgType = Logon (A) 
| 34 MsgSeqNum = 1 
| 49 SenderCompID = testusr4109 
| 52 SendingTime = 20101124-20:27:25.000 
| 56 TargetCompID = OANDA 
+-BODY 
| 98 EncryptMethod = NONE_OTHER (0) 
| 108 HeartBtInt = 300 
| 141 ResetSeqNumFlag = Y 
| 554 Password = Passw0rd 
+-TRAILER 
| 10 CheckSum = 133 
+========
```

FIXメッセージの例:実行レポート(wikipedia参照)
```
+-HEADER 
| 8=FIX.4.2 
| 9=176 
| 35=8 
| 49=PHLX 
| 56=PERS 
| 52=20071123-05:30:00.000 
| 11=ATOMNOCCC9990900 
| 20=3 
| 150=E 
| 39=E 
| 55=MSFT 
| 167=CS 
| 54=1 
| 38=15 
| 40=2 
| 44=15 
| 58=PHLX EQUITY TESTING 
| 59=0 
| 47=C 
| 32=0 
| 31=0 
| 151=15 
| 14=0 
| 6=0 
| 10=128 
```
## ヘッダおよびトレーラ
すべての FIX メッセージは、ヘッダフィールドで始まり、トレーラ<10>フィールドで終わらなけれ ばなりません。 

### ヘッダーフィールド
すべての FIX メッセージで最初にこなければならない

### トレーラフィールド
FIX メッセージの終りにこなければならない


#メッセージまとめ
ボディーの内容とかは繋ぐところの使用によって変わってくるが、FIXとしてよく使いそうなメッセージをまとめてみた。

## 管理メッセージ　
## Logon(アウトバウンド、インバウンド)<A>
ユーザー承認を行い、セッションを開始する。
どのアプリケーションでも、これがFIXセッション開始リクエストを送信する最初のメッセージでなければならない。
Logonリクエストを認証できない場合
Logout<5>または Reject<3>メッセージを返す、またはサービス拒否（DoS）攻撃に対する予防措置として全く応答しないこともある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289294/a886cbc1-73fa-d46b-db61-d3d4411a0b5f.png)

注　OANDAだけ？）ログオンには、ResetSeqNumFlag=Y が使用されなければならない。
 HeartBtInt<108>フィールドは、ハートビート・メッセージを生成するためのタイムアウト・イ ンターバルを宣言する
（同じインターバルが両方の側で使用されます）。このフィールドは、 Logon リクエストに含まれている必要があり、OANDA サーバからの Logon メッセージにも繰り返されなければならない。HeartBtInt の値は、少なくとも 30 秒必要で、推奨 HeartBtInt 値 は 300 秒（5 分）

## New（インバウンド）<B>
Newsメッセージはサーバから返されるメッセージ
動作変更または近日中のリリースに関する 重要な情報を提供する
このメッセージに表示されるバージョン番号は、番号のみで表され、ピリオドで区切られています （例、”version: 2.2”）。バージョンのアップデートは、ご利用規約の修正を含む場合があり、それに従 い顧客プログラムの変更が必要になる場合がある


## Logout（アウトバウンド、インバウンド）<5>
Logout<5>メッセージは、FIX セッションの停止を開始または確認します。
Logout メッセージのや り取りをせずに接続解除されたセッションは、（ネットワーク障害などの）異常状態として解釈さ れなければなりません。 セッションを終了する前に、クライアントは OANDA サーバが確認のための Logout メッセージを 返すまで待たなければなりません。これにより、サーバは最後の操作を完了することができます。

## クライアント・リクエスト（アウトバウンド）
### New Order – Single（アウトバウンド）<D>
Forex 注文を OANDA に出すためにクライアント側で使用されます。
これは、Login セッションが確立した後にのみ出すことができます。
 OANDA サーバは、New Order - Single リクエストに対し、Execution Report<8>で応答します。
この メッセージは、注文の執行が成功したかどうかの情報を提供します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289294/6eca24dd-29a5-8fdd-1ce0-0aee4a1e27ad.png)

### Order Cancel Request(アウトバウンド)<F>
Order  Chancel Request<F>メッセージは、注文の取り消しを要求します。
Order Chancel Requestは注文がまだ執行されず、取り消しできる場合にのみ受け付けられます（そして、Execution Report<8>が返されます）。そうでない場合は、Order Chancel Reject<9>メッセージが返されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289294/9679f54c-576f-1cb0-1dde-a7dae39354c7.png)

Order Status Request(アウトバウンド)<H>
以前の注文に関する情報は、Oreder Status Request<H>メッセージで得ることができます。Execution Reportの返信メッセージは、リクエストされた注文の情報を提供します。

注文の状況は、注文の完了（約定、有効期限終了、取り消し）後、少なくとも1カ月間は入手することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289294/ebdf6c5d-a148-16c6-1d22-9e17e14757ce.png)


## Market Data Request(アウトバウンド)<V>
一部のシステムでは、サブスクリプションベースでリアルタイムの見積もり、注文、取引、取引量、建玉、および/またはその他の価格情報を送信できます。
特定の証券や外国為替相場の市場データのための一般的な要求です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289294/aaff6af0-c41a-9b8e-0a8a-515757004bb0.png)


*Market Data Requestのタイプ* 
Snapshot(SubscriptionRequestType = 0)は、1回限りのリクエストに最適です。継続的にレートの更新が必要な場合は、短時間のスナップショット・ポーリングの利用ではなく、サブスクリプションリクエスト（スナップショット＋更新、(SubscriptionRequestType = 1)）をお薦めする。

## サーバーレスポンス（インバウンド）
### Execution Report（インバウンド）<8>
Execution Report<8>メッセージは、クライアントの注文が執行または拒否されたことを報告するために、OANDAサーバによって返されます。このメッセージの例として以下が挙げられる。

注文の受領確認（New Order - Single<D>）
 既存の注文への変更の確認 （Order Cancel Request <F>、Order Cancel / Replace Request <G>） 
新規注文拒否

拒否された注文変更またはキャンセルは、Order Cancel Reject<9>経由で通知


### Order Chancel Reject(インバウンド) <9>
Order Cancel Reject<9>メッセージは、Cancel Requestまたは Cancel/Replace Requestメッセージが失敗したときに、サーバによって出されます。 値段または数量の変更リクエストは、残高数量があるときのみ執行されます。約定済みの注文は変更 できません。

### Reject(インバウンド)<3>
Rejectメッセージは、メッセージ受信時にシンタックスエラーまたはその他のコーディング論理違反により、適切に処理できないときに、サーバから出されるメッセージ。

### Business Message Reject(インバウンド)<j>
セッションレベル規則は満たしているがビジネス要件を満たしていないクライアントのリクエストメッセージに対し、他に方法がない場合には Bussiness Message Reject<j>メッセージで拒否します。

### Market Data - Snapshot/Full Refresh<W>
Market Data - SnapShot/Full Refresh<W>メッセージは、Market Data Request<V>メッセージへの応答です。
Snapshot<W>メッセージは、そのメッセージのMDReqIDタグ経由で Market Data Request<V>を提供します。
１つの<V>メッセージで複数のシンボルが要求された場合、かく<W>メッセージは１つのシンボルの情報のみを提供するため、結果として複数の<W>レスポンスが返されます。

### Market Data - Incremental Refresh<X>
Market Data Request<V>サブスクリプションリクエストにおいて、リクエストしたシンボルのスナップショットが送信された後、レートの更新に関するIncremental refresh<X>メッセージが送信されます。レート変更がない場合は、メッセージは送信されません。


## FIXデータタイプまとめ
char(文字型)：１文字分の値で、英数字または区切り文字を除く句読点を含みます。
文字型フィールドは全て、大文字小文字を区別します。

data(データ型)：フォーマットまたはコンテンツ制限のないローデータ。データ・フィールドの直前には常にlengthフィールドが先行しています。lengthフィールドは、データ・フィールドの値のバイト数を指定しなければなりません。(終了SOHまで。そのSOHは含みません)。
注）これ他のフィールドの１つの値には、区切り文字(SOH)を入れることができます。全てのフィールドがSOHで終了するため、このフィールドのために指定された値の後には、区切り文字SOHガルずく必要があることに留意してください。

int(整数型)：カンマまたは少数点以下の桁を除いた一連の数字と任意符号文字(ASCII文字”-”および”0”-“9”)符号文字は１バイト使用します (すなわち、正の整数は”99999”、負の整数は”-99999”)
整数値は先頭にゼロを含むことができます。

length(長さ)：データ・フィールドの値の倍と数を示す整数。

LocalMktDate(ローカルマーケット日付)：ローカツマーケットの日付

price(値段)：小数点第５位までのせいの浮動値

string(文字列)：区切り文字を除くあらゆる文字と句読点を含むことができるフリー・フォーマットの一連の英数字。charフィールドは全ての大文字小文字を区別。

UTCDate(UTC日付)：UTCTiimestampのYYYY MMDD部分

UTCTimeOnly(UTC時刻のみ)：UTCTimestampのHH:MM:SS部分

UTCTimeStamp(UTCタイムスタンプ)：UTC(世界協定時、または”GMT”)の時刻/日付の組み合わせで、YYYYMMDD-HH:MM:SS(1秒ごと)またはYYYYMMDD-HH:MM:SS:sss(1000ぶんの1秒)フォーマットのいずれかで表示されます。
コロン、ダッシュ、およびピリオドが必要です。
LocalMktateの対照となるものです。

#記事のまとめ
まだまだわからないことが多いので、すでにFIXを業務で使ってる人とかは、新人の備忘録だと思ってくれればと思います…
同じような温度感の方には少しでも参考になれば光栄です。

QuickFix/J　とかで実装してみて、理解が深まったら、この記事は編集していきます…。