1. Trade Tracker とは
Trade Tracker は、FX トレード管理サービス「Myfxbook」の公開 API を活用して開発した Android アプリです。自身のトレード記録をスマートフォンからリアルタイムに確認・分析することを目的としています。
1-1. 開発の背景
Myfxbook はトレード記録の管理・公開に広く利用されている海外の無料サービスです。MT4 / MT5 と連携させることで、損益グラフや統計データを自動的に記録・公開できます。FX の自動売買(EA)を運用しているトレーダーの多くが利用しています。
しかし公式モバイルアプリには以下の課題がありました。
- 欲しい統計情報(時間帯別・曜日別成績など)が取得できない
- 複数口座の合算サマリーが確認しにくい
- 取引履歴の分析機能が限定的
これらの課題を解消するため、Myfxbook の公開 API を活用して独自の Android アプリを開発しました。開発には AI コーディングアシスタント「Claude Code」を活用し、設計から実装・デバッグまでを AI と協働することで短期間でのプロトタイプ完成を実現しています。
1-2. 公式アプリとの比較
| 機能 | 公式アプリ | Trade Tracker |
|---|---|---|
| 残高・損益確認 | ✓ | ✓ |
| 取引履歴閲覧 | ✓(件数制限あり) | ✓(全件・DB蓄積) |
| 時間帯別成績 | × | ✓(JST基準) |
| 曜日別成績 | × | ✓ |
| 通貨ペア別成績 | △ | ✓ |
| 複数口座合算 | × | ✓ |
| CSVインポート | × | ✓ |
| 残高推移チャート | ✓ | ✓(期間選択付き) |
2. 技術スタック
Android 開発のモダンなアーキテクチャとライブラリ群を採用しています。
| カテゴリ | 採用技術 | 役割 |
|---|---|---|
| 言語 | Kotlin | Android 公式推奨言語。null 安全・コルーチン対応 |
| UI | Jetpack Compose | 宣言型 UI フレームワーク。従来の XML レイアウトに代わる最新手法 |
| デザイン | Material Design 3 | Google 推奨の UI コンポーネント・カラーシステム |
| ネットワーク | Retrofit + Gson | Myfxbook REST API との通信・JSON デシリアライズ |
| ローカル DB | Room | SQLite のラッパー。取引履歴を端末内に蓄積 |
| DI | Hilt | 依存性注入。ViewModel・Repository・DB の生成を管理 |
| 状態管理 | StateFlow + ViewModel | MVVM パターンの実装。UI 状態を一元管理 |
| 永続化 | DataStore | セッション ID・ログイン情報の暗号化保存 |
| 非同期処理 | Coroutines + Flow | API 通信・DB 操作を非同期で処理 |
3. アーキテクチャ・データフロー
3-1. MVVM アーキテクチャ
本アプリは MVVM(Model-View-ViewModel)アーキテクチャを採用しています。UI・ロジック・データを明確に分離することで、テスタビリティと保守性を高めています。
API から取得したデータは Room DB へ蓄積し、全件を対象に統計計算を行います。Myfxbook の取引履歴 API は 1 リクエストあたり最大 40 件の制約があるため、毎回の取得分を DB へ追記することで全件データを維持します。
3-2. API シーケンス
3-3. Room DB スキーマ
4. 画面構成・機能一覧
4-1. ログイン画面
Myfxbook のメールアドレスとパスワードでログインします。API のレスポンスとして発行されるセッション ID を Jetpack DataStore に暗号化して保存するため、アプリ再起動後の再ログインは不要です。
注意: セッション ID を URL パラメータとして送信する際、そのままでは二重エンコードが発生し認証エラーになることがあります。Retrofit の @Query(encoded=true) アノテーションを使用してエンコード済み文字列をそのまま送信することで解決しています。
4-2. ポートフォリオ画面
ログイン後に表示される口座一覧画面です。各口座について残高・本日損益・損益合計・ゲイン率をカード形式で表示します。複数口座が登録されている場合は、画面上部に合算サマリーカードを表示します。Pull-to-refresh による手動更新に対応しています。
4-3. 取引詳細画面(6 タブ)
| タブ | 表示内容 | 主な活用シーン |
|---|---|---|
| 統計 | 残高・有効証拠金・損益サマリー、残高推移ラインチャート(1M/3M/6M/1Y/ALL) | 口座全体のパフォーマンス把握 |
| 損益 | 月次棒グラフ(利益月:緑 / 損失月:赤)、月別損益テーブル | 月ごとの収支確認・悪い月の特定 |
| 履歴 | 全取引履歴(新しい順)、月単位スクロールロード | 個別トレードの振り返り |
| 分析 | ゲイン分析・時間帯別・通貨ペア別・曜日別の成績 | 得意な時間帯・通貨ペアの把握 |
| 取引 | 現在のオープントレード一覧 | 保有中ポジションの確認 |
| 注文 | 未決済注文一覧 | 指値・逆指値の確認 |
5. 使い方ガイド
5-1. 初回セットアップ
- Myfxbook(myfxbook.com)にアカウント登録する(無料)
- MT4 / MT5 と Myfxbook を連携させる
- Trade Tracker アプリを起動し、Myfxbook のメールアドレスとパスワードを入力してログイン
- 口座一覧が表示されたら、分析したい口座を選択する
5-2. 過去データのインポート
API 経由で取得できる取引履歴は直近 40 件が上限です。それ以前のデータを分析に含めるには、CSV インポート機能を使用します。
- Myfxbook の Web サイトにログインし、取引履歴を CSV 形式でエクスポート
- Trade Tracker のハンバーガーメニュー(≡)から「インポート」を選択
- エクスポートした CSV ファイルを選択すると、DB に追記される
- 全期間の統計・分析データが表示される
6. 主な実装上のポイント
6-1. API 40 件制限の回避
Myfxbook の get-history.json は、日付パラメータを指定しても 1 リクエストで返せる件数が最大 40 件に固定されています。この制約を Room DB への蓄積方式で回避しています。
// MyfxbookApiService.kt
@GET("get-history.json")
suspend fun getHistory(
@Query("session", encoded = true) session: String,
@Query("id") accountId: String,
@Query("start") start: String, // "2000.01.01"
@Query("end") end: String // 今日の日付
): Response<TradeHistoryResponse>
毎回のリクエストで最新 40 件を取得し、upsertAll() で DB に追記します。統計計算はすべて DB の全レコードを対象に行うため、API の件数制限に影響されません。
6-2. UTC → JST 変換
Myfxbook API はすべての時刻を UTC で返します。日本のトレーダーにとって時間帯別成績を UTC で分析しても意味がないため、DB 保存時に JST へ変換しています。
// UTC 文字列 → JST ZonedDateTime に変換
fun parseToJst(utcStr: String): ZonedDateTime {
val utc = LocalDateTime.parse(utcStr, DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm"))
return utc.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.of("Asia/Tokyo"))
}
// 時間帯別集計(JST 基準)
val hourlyStats = trades.groupBy { parseToJst(it.openTime).hour }
6-3. 認証情報の安全な管理
セッション ID とログイン情報は Jetpack DataStore(Preferences)に保存します。SharedPreferences と異なり DataStore は非同期・型安全であり、EncryptedSharedPreferences を使わずとも Android Keystore と組み合わせた暗号化が実現できます。
// CredentialsDataStore.kt(抜粋)
val SESSION_KEY = stringPreferencesKey("session_id")
suspend fun saveSession(session: String) {
dataStore.edit { prefs ->
prefs[SESSION_KEY] = session
}
}
val sessionFlow: Flow<String?> = dataStore.data
.map { prefs -> prefs[SESSION_KEY] }
6-4. 取引履歴の重複排除
API を繰り返し呼び出すと同じ取引が複数回 DB に書き込まれる恐れがあります。Room の OnConflictStrategy.REPLACE と複合ユニークキー(accountId + openTime + symbol + openPrice)を組み合わせることで、重複なく蓄積できます。
7. Android 開発技術の解説
7-1. Jetpack Compose とは
Jetpack Compose は Android の最新 UI フレームワークです。従来は XML ファイルでレイアウトを定義し、Kotlin コードと紐づける方式でしたが、Compose では UI をすべて Kotlin コードで宣言的に記述します。状態が変化すると UI が自動的に再描画されるため、状態管理が直感的になります。
7-2. Room DB とは
Room は Android 公式の SQLite ラッパーライブラリです。SQL クエリをアノテーションで定義でき、コンパイル時に型安全性を検証します。Flow との組み合わせにより、DB の変更をリアルタイムに UI へ反映できます。
7-3. Hilt(依存性注入)とは
Hilt は Dagger をベースにした Android 向け DI(依存性注入)フレームワークです。ViewModel・Repository・Retrofit インスタンス・Room DB などの生成と管理を自動化します。手動でインスタンスを渡す実装に比べ、テストの差し替えや設定の一元管理がしやすくなります。
8. 開発プロセス
最初のコミット(ログイン・取引履歴一覧・損益サマリー)から現在の 6 タブ構成まで、主要な実装の流れを示します。
| フェーズ | 実装内容 |
|---|---|
| フェーズ 1 | ログイン・ポートフォリオ画面・取引履歴 4 タブの基本実装。Hilt / Room / DataStore の導入 |
| フェーズ 2 | JST 変換・損益表示の書式統一(¥マーク・小数切り捨て) |
| フェーズ 3 | 残高推移ラインチャート(Compose Canvas・ベジェ曲線・グラデーション)の実装 |
| フェーズ 4 | 損益タブ(月次棒グラフ・年別展開)の実装 |
| フェーズ 5 | 分析タブ追加(ゲイン分析・時間帯別・通貨ペア別・曜日別) |
| フェーズ 6 | Room DB 全件蓄積・CSV インポート / エクスポート・ログアウト・複数口座合算の実装 |
| フェーズ 7 | UI 改善・バグ修正(ページネーション・スクロールロード・期間統計の共有) |
9. 今後の改善候補
- 通貨ペア別チャートへの期間フィルタ追加
- ホーム画面ウィジェットによる残高・損益のクイック確認
- 本日損益の取得精度向上(API の
DailyData.profitと公式アプリの値の差異を解消) - プッシュ通知(決済アラート)
10. 動作要件
- Android 8.0(API レベル 26)以上
- Myfxbook アカウント(無料登録可)
- インターネット接続環境
サラリーマンの相場道 
