[第1回] Pythonを使ってMT5からトレード履歴をExcelファイルに出力し、トレード記録作業を簡略化してみた

# 本シリーズの目次
1. 第1回: 前提知識などの解説 ←本記事
2. [第2回: コード前半部分の解説](https://qiita.com/gappac/items/a48176e2114164ac090d)
3. [第3回: コード後半部分の解説](https://qiita.com/gappac/items/45ff3bd7506511cb515e)

# はじめに
トレードノート書くのメンドくね？？

最近FXに挑戦中ですが、成長のためには振り返りと反省が不可欠。ということでトレードノートを付け始めました。
しかし、ノートを付け始めたは良いものの
「日付とか通貨ペアとかエントリー価格とか損益比とか、いちいち書くのだり～～～～～」
と思うようになりました。

記録するのが苦しくなってトレードノートを書かないようになったのでは、何の意味もありません。。。
というわけで、PythonのMetaTrader5ライブラリとopenpyxlライブラリを利用して、MT5からトレード履歴を取得してExcelファイルに出力してくれるプログラムを書いてみました。

### 目的
- トレードノート記録作業の簡略化

### 対象読者
- デスクトップ版MT5を使ってFXをしている人（※ブラウザ版は対象外）
- トレードノートを付けるのが面倒な人

### この記事でわかること
- PythonとMT5の接続方法
- MetaTrader5ライブラリのざっくりとした使い方
- openpyxlライブラリのざっくりとした使い方

# 前提条件・準備環境
## バージョン

#### Pythonのversion: 3.11.9
バージョン確認コマンドは以下の通り

```Bash
python --version
```

#### MT5のversion: 5.00
MT5のバージョンはウィンドウ上部の「ヘルプ」タブから「バージョン情報」で確認できます。

## 必要なライブラリのインストール
必要なのはMetaTrader5と、openpyxlの2つ。
以下のコマンドでそれぞれインストールできます。

```Bash:MetaTrader5のインストール
pip install MetaTrader5
```

```Bash:openpyxlのインストール
pip install openpyxl
```

# トレード履歴の取得方法
MQL5というサイトにリファレンスがあるので、詳しくはこちらをチェックしてください

https://www.mql5.com/ja/docs/python_metatrader5

## MT5との接続
PythonからMT5のトレード履歴を取得するために、まずはMT5との接続を以下のコードによって確立します。

```Python:MT5と接続
import MetaTrader5 as mt5

mt5.initialize(
  path                      # MetaTrader 5ターミナルのEXEファイルへのパス file
  timeout=TIMEOUT,          # timeout
  login=LOGIN,              # 口座番号
  password="PASSWORD",      # パスワード
  server="SERVER"           # ターミナルで指定されているサーバ名
  )
```

また、MT5を起動し、口座にログインした状態でPythonプログラムを実行するのであれば、引数なしでも大丈夫です。

```Python:MT5と接続
mt5.initialize()
```

プログラム終了時には接続を切断するのも忘れずに。以下のコードで接続を切断できます。
```Python:MT5との接続を切断
mt5.shutdown()
```

## 注文履歴の取得
トレード履歴には注文履歴（history_orders）と取引履歴（history_deals）があります。

トレーダーが注文ボタンを押すことで注文がFX業者のサーバーに送信され、その注文が成立して初めて取引となります。

注文履歴（history_orders）の取得方法は以下の3通り

```Python:注文履歴を取得その1
mt5.history_orders_get(
  date_from,           # 注文がリクエストされている最初の日
  date_to,             # 注文がリクエストされている最後の日
  group="GROUP"        # 注文を銘柄で選択するためのフィルター
  )
```

```Python:注文履歴を取得その2
mt5.history_orders_get(
  ticket=TICKET       # 注文チケット
)
```

```Python:注文履歴を取得その3
mt5.history_orders_get(
  position=POSITION   # ポジションチケット
)
```

注文チケット・ポジションチケットというのは、注文ごとないしポジションごとに割り振られる整数値で、それぞれの識別のために用いられるものです。わからなくても大丈夫

戻り値の形式はnamedtupleで、主要な要素をあげると以下の通り。

| フィールド名               | 型        | 説明                                                                      |
| -------------------- | -------- | ----------------------------------------------------------------------- |
| **ticket**           | `int`    | 注文チケット番号                                                              |
| **time\_setup**      | `int`    | 注文の発行時刻（UNIX 時間：秒）                                       |
| **time\_done**       | `int`    | 注文が約定またはキャンセルされた時刻（UNIX 時間：秒）                                           |
| **type**             | `int`    | 注文種別（`ENUM_ORDER_TYPE`。例：`0=BUY`, `1=SELL`, `2=BUY_LIMIT`…）|
| **state**            | `int`    | 注文状態（`ENUM_ORDER_STATE`。例：`PLACED`, `FILLED`, `CANCELED`…）              |
| **magic**            | `int`    | EA 用のマジックナンバー                                                           |
| **position\_id**     | `int`    | この注文で開かれた／クローズされたポジションのチケット ID（`ORDER_POSITION_ID`）                     |
| **volume\_initial**  | `float`  | 発行時の注文サイズ（ロット数）                                                         |
| **price\_open**      | `float`  | 発行時に指定された価格                                                             |
| **sl**               | `float`  | ストップロスレベル                                                               |
| **tp**               | `float`  | テイクプロフィットレベル                                                            |
| **price\_current**   | `float`  | 現在のティック価格（未約定注文）または約定価格（履歴注文）                             |
| **price\_stoplimit** | `float`  | StopLimit 注文時の発注価格                                                      |
| **symbol**           | `string` | 通貨ペアなどのシンボル名                                                            |
| **comment**          | `string` | 注文コメント             　                                                      |


## 取引履歴の取得
取引履歴（history_deals）の取得方法は以下の3通り

```Python:取引履歴を取得その1
mt5.history_deals_get(
  date_from,           # 取引がリクエストされている最初の日
  date_to,             # 取引がリクエストされている最後の日
  group="GROUP"        # 銘柄の取引を選択するためのフィルター
  )
```

```Python:取引履歴を取得その2
mt5.history_deals_get(
  ticket=TICKET       # 注文チケット
)
```

```Python:取引履歴を取得その3
mt5.history_deals_get(
  position=POSITION   # ポジションチケット
)
```

注文履歴（history_orders）の場合と同じです。戻り値の形式はnamedtupleで、主要な要素をあげると以下の通り。

| フィールド名           | 型        | 説明                                                                                       |
| ---------------- | -------- | ---------------------------------------------------------------------------------------- |
| **ticket**       | `int`    | 取引チケット番号                                                    |
| **order**        | `int`    | この取引を生成した注文のチケット番号                                                      |
| **time**         | `int`    | ディール実行時刻（UNIX時間：秒）                                                                      |
| **type**         | `int`    | ディール種類（`ENUM_DEAL_TYPE`。例：`0=BUY`, `1=SELL`, `2=BALANCE`…）                              |
| **entry**        | `int`    | エントリ種別（`ENUM_DEAL_ENTRY`。例：`0=IN`, `1=OUT`, `2=INOUT`…）                                 |
| **magic**        | `int`    | マジックナンバー（EA識別用）                                                                         |
| **position\_id** | `int`    | 関連ポジションのチケット番号（`DEAL_POSITION_ID`）。開設・変更・決済されたポジションを示す                                  |
| **volume**       | `float`  | 取引量（ロット数）                                                                               |
| **price**        | `float`  | 取引価格                                                                                    |
| **commission**   | `float`  | コミッション（手数料）                                                                            |
| **swap**         | `float`  | スワップ（オーバーナイト金利）                                                                         |
| **profit**       | `float`  | 損益                                                                               |
| **fee**          | `float`  | 即時課金手数料（`DEAL_FEE`）                                                                     |
| **symbol**       | `string` | シンボル名（例：`EURUSD`）                                                                       |
| **comment**      | `string` | ディールコメント                                                                               |

# Excelファイルへの出力
基本的な操作のみ書きます。

新たにワークブック（Excelファイル）を作成することもできますが、今回は既にトレードノートとして使用しているワークブックのテーブルに追記していきます。

```Python:Excel基本操作
import openpyxl
from openpyxl.styles import Font, Alignment

wb = openpyxl.load_workbook(FILE_PATH)     # FILE_PATHのワークブックを指定
ws = wb[SHEET_NAME]                        # SHEET_NAMEという名前のワークシートを指定
table = ws.tables[TABLE_NAME]              # TABLE_NAMEという名前のテーブルを指定
cell = ws["A1"]                            # wsのA1セルを指定

# セルに値を入力
cell.value = 1234      

# 太字・斜体・赤文字・文字サイズ
cell.font = Font(bold=True, italic=True, color="FF0000",size=14) 
# 黄色に塗りつぶし
cell.fill = PatternFill(fill_type="solid", start_color="FFFF00", end_color="FFFF00") 
# 太線で囲う
cell.border = Border(left=Side(style='thick', color='000000'),
                    right=Side(style='thick', color='000000'),
                    top=Side(style='thick', color='000000'),
                    bottom=Side(style='thick', color='000000'))
# 中央揃え
cell.alignment = Alignment(horizontal='center', vertical='center')
# 数値フォーマット
cell.number_format = '#,##0.00'

# FILE_PATHにワークブックを保存
wb.save(FILE_PATH) 
```

# まとめ
ということで、まずは前提知識など基本的なことを書いてみました。次回は本記事で書いたことを用いて作成したプログラムを解説していきます。次回記事もどうぞ。

https://qiita.com/gappac/items/a48176e2114164ac090d

コード全文とトレードノートのテンプレートはgithubからダウンロードできます。

https://github.com/gappac/export_trade_history_with_python

## 参考リンク
https://www.mql5.com/en/docs/python_metatrader5