はじめに
過去記事は「auカブコム証券のkabuステーションREST APIに関する記事一覧」。
そろそろスタンドアロン前提だと、作れば作るほどPC環境が辛くなってくるので、自前のRESTサーバーを立てて、auカブコム証券APIに直接関係ない処理をスケールアウトできるようにする。
レポジトリとプロジェクト
プロジェクトの種類が異なるため、レポジトリ(kabusapisrv)を新規に作成した。
mavenプロジェクトをspring-bootを選んだが、バージョンが古くて、自分でpom.xmlを編集するのとあまり変わらなかった。
- org.springframework.boot / spring-boot-starter-parent / 2.7.4
- org.apache.httpcomponents / httpclient (HTTP接続テスト用)
実装
パッケージとクラス
RDBを使っていない自前でテキストファイルのI/Oの永続化だが、MVCぽくパッケージとクラスを作成する。
保存先は、今まで/tmp/chart/だったので、競合しないように/tmp/server/chart/
にする。
- server.rest / ChartDataController
- server.service / ChartDataService
- server.repository / ChartDataRepository
テストPGM
他のPGMからHTTPアクセスすることになるが、将来自動テストのために、自分自身にHTTPアクセスするテストPGMも作って、接続確認/単体テストに使う。
- test / MainTestClient
Spring Bootを選ぶと、標準でjacksonが使えるので、これを使って、Javaインスタンス→JSON文字列変換を行う。
なお、既存のPGMに組み込もうと思ったら、swaggerがgsonを使っているので、この部分が違うソースになる。
private static String jsonData(ChartData cd) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(cd);
return json;
}
HTTPアクセスはcommons httpClientのころから使っていたので、Apache HttpClientを使う。
JSONをまるごとPOSTしたいので、StringEntityを作成する。この部分はString dataを渡すので、JSONパーサーは関係しない。
StringEntity entity = new StringEntity(data, ContentType.APPLICATION_JSON);
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
テスト
SampleTomcatApplicationを実行して、ポート8080でHTTPサーバーを立ち上げる。
MainTestClientを実行すると、架空のcode=123で3レコードが送信され、/tmp/server/chart/123にChartData.csvが作成される。
追記:重複チェック付きのチャートデータ登録
r1版は無条件に追記していたが、r2版として、メモリ上のListとSetに読み込み、Setに含まれているかどうかのチェックを追加する。
追記:チャートDBの登録
別URI(/chartDb/r1)でチャートDBの上書き保存するAPIを追加する。
追記:レポジトリのロードと一覧
ディレクトリ内のすべてのファイルをロードするURI(/repo/load)と、ロードされている一覧を返すURI(/repo)を追加する。
レスポンスはHTMLではないが、RESTでなくWeb扱いのコントローラーで作る(server.web.RepositoryController)。
追記:マージツールをRESTサーバーへ移植
v38.MainMergeChartData_r10を、RESTサーバーのマージURI(/merge)に移植する。
ただし、/tmp/server/dbと/tmp/server/chartから毎回ファイルを読んでいるが、ChartDbRepositoryとChartDataRepositoryに持っている。
/tmp/server/chart/*のディレクトリ一覧のみChartDataRepository.list()が用意している。
追記:CalendarLogicとChartDbRepositoryが連携
CalendarLogic.readCalendar()を廃止し、ChartDbRepositoryからListをinitCalendar()に渡す。
ChartDbRepositoryは、load()とwrite()のタイミングで、CalendarLogicに反映する。
追記:MergeChartDataCommon_r10とChartDbRepositoryが連携
MergeChartDataCommon_r10.readDbChartData()にChartDbRepositoryを渡すことで、ファイルを直接読まずに、Repositoryが管理している最新のリストを取得する。
追記:MergeChartDataCommon_r10とChartDataRepositoryが連携
MergeChartDataCommon_r10.readCsvChartData()にChartDataRepositoryを渡すことで、ファイルを直接読まずに、Repositoryが管理している最新のリストを取得する。
追記:テクニカル指標計算ツールをRESTサーバーへ移植
v38.MainCalcIndicator_r10を、RESTサーバーのテクニカル指標計算URI(/calc)に移植する。
マージツールと同様に、/tmp/server/chartから毎回ファイルを読んでいる。
ただし、今回の入力ファイルは、マージツールの出力ファイルのため、ChartDbRepositoryには登録されずに、直接ファイルに保存されている。
効率化のため、ファイルに保存せずにパイプのようなデータ連携をしたいので、別途Repositoryを作成する。
追記:MergeChartDataCommon_r10とCalcIndicatorServiceの間にMergeDataRepositoryが連携
MergeDataRepositoryを作成して、MergeChartDataCommon_r10の出力と、CalcIndicatorServiceの入力につなげる。
追記:gitレポジトリ名の変更(kabusapisrv -> kabusapp-restserver)
後からgitレポジトリを追加していくと、紛らわしい名前で勘違いするので、ハイフンを付けた名前に変更する。
追記:イベントトリガー発火ツールをRESTサーバーへ移植
v39.MainTriggerIndicator_r11を、RESTサーバーのトリガーURI(/trigger)に移植する。
テクニカル指標計算ツールと同様に、/tmp/server/chartから毎回ファイルを読んでいる。
後から、効率化のため、テクニカル指標計算ツールの出力ファイルのために、別途Repositoryを作成する。
追記:CalcCoordinator_r10とTriggerCoordinator_r11の間にIndicatorDataRepositoryが連携
IndicatorDataRepositoryを作成して、CalcCoordinator_r10の出力と、TriggerCoordinator_r11の入力をつなげる。
ファイル数が多くなってきたので、従来の/repoを以下のようなサマリーにして、/repo/listがファイルリストを表示する。
ChartDataRepository: File: 14 , Line: 60228
ChartDbRepository: File: 161 , Line: 401295
MergeDataRepository: File: 196 , Line: 784320
IndicatorDataRepository: File: 1568 , Line: 69742
追記:イベントトリガー発火ツールをRESTサーバーへ移植(Tickデータ監視)
v40.MainTriggerChartData_r12を、RESTサーバーのトリガーURI(/trigger/tick)に移植する。
TickデータはChartDataRepositoryで管理されているので、ファイルから読まない。
なお、v39.MainTriggerIndicator_r11のイベントトリガーとは監視対象が異なるため、こちらをトリガーURI(/trigger/indicator)に変更し、両方を順番に実行するトリガーURI(/trigger)の3つのエントリーポイントを用意する。
ほとんどChartDataという名称を使ってきたが、Tickデータは、4本値と違い同一時刻の複数レコードを持つことが出来るため、コンソールアプリ側から出来る限りChartDataをTickDataに変更する。ツールエントリv40.MainTriggerChartData_r12はv40.MainTriggerTickData_r12となる。なお、4本値とTickデータの両方を含む場合(広義のChartData)は、マージ後の4本値(狭義のChartData)と区別しない。
追記:名称ChartDataをTickDataに変更
イベントトリガーに関連する部分のみ、ChartDataをTickDataに変更する。
クラス名
v40.MainTriggerChartData_r12 to v40.MainTriggerTickData_r12
v40.TriggerChartData_r12 to v40.TriggerTickData_r12
javadocコメント
チャート to ティック
マージ to 抽出
ファイル名
TriggerIndicator.out to TriggerTickData.out
追記:マージツールを先頭カラムのタイムスタンプに対応する
マージURI(/merge)を/merge_r10に変更する。
v45(r17)をRESTサーバーへ移植し、マージURI(/merge)とする。
以下の修正を反映する。
- 定数名CHART_CSV_FILENAMEに統一
- 同じChartData.csvの読み込みを1回にする
- fix 置換時にprevが代入されていない/readCsvChartData()からreadCsvChartLine()を切り出し
- CSVファイルのコメント行チェック
追記:Tickデータのトリガーを先頭カラムのタイムスタンプに対応する
トリガーURI(/trigger/tick)を対応する。
以下の修正を反映する。
- MergeChartInfo_r10をv43.beanからbeanに移動
- CalcIndicatorInfo_r10をv43.beanからbeanに移動
- TriggerIndicatorInfo_r11をv39.beanからbeanに移動/EventInfo_r11に変更
- EventInfo_r11にComparable実装/idの変更(日付を前へ)
- コピーコンストラクタに置き換え(未使用)
追記:未使用のURIを削除
旧バージョンのソースを残すと、メンテが大変なので、未使用のURIを削除する。
アーカイブしようかと思ったが、依存性が強く、まるごとコピーとほとんど変わらないので、止める。
なお、APIバージョンは先頭の方がよかった(/r1/chartData)。
- /chartData/r1
- /merge_r10
- /calc_r10
- /trigger_r10
- /trigger/indicator_r10
- /trigger/tick_r10
追記:監視URI(/watch)、/chartDataと関連付け
コンソールアプリのファイル監視がWatchChartDataであったため、URIを/watchとしたが、WatchChartDataがChartData.csvの更新を監視するのと同様に、/chartData/r2にチャートデータを受信したときに、連携して起動する。
URIは、手動でテスト目的。
githubソース