Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

RedisTimeSeriesで金融アプリケーションを構築する方法:株価とテクニカル指標の時系列データ管理

投資家は、大きく分けて2つのタイプに分類できます。ファンダメンタル投資家は、企業のビジネスモデル、売上高、利益、キャッシュフロー、現在のバリュエーション(評価額)、リスク、成長見通しなどの基本的な指標をもとに、その企業へ投資すべきかどうかを判断します。ウォーレン・バフェットは、徹底したファンダメンタル分析によって割安な企業を見つけ出し、世界有数の富豪として名を馳せました。

一方で、テクニカル投資家は企業のファンダメンタルズにはほとんど、あるいはまったく注目せず、数百に及ぶテクニカル指標から買い・売り・保有のシグナルを導き出すことに集中します。こうしたテクニカル投資家は、日次・週次・月次の単位で取引を行います。

ここで、どちらの投資スタイルが優れているかを論じるつもりはありません。しかし、ファンダメンタル投資家とテクニカル投資家のいずれも、数百から数千ものデータソースを調査・分析し、それに基づいて意思決定を行っているという点は共通しています。

ファンダメンタル投資家は、世界中の数千社の企業と数百の業界にわたる貸借対照表、損益計算書、キャッシュフロー計算書、人口動態のトレンド、テーマ別トレンド、社会トレンドなどを研究します。そして、そのデータの上に財務モデルや分析基盤を構築し、企業の将来像や成長見通しをより深く理解しようとします。

テクニカル投資家は、時間単位または日単位で数百のテクニカル指標を監視し、投資シグナルを導き出します。テクニカル指標に依存する投資家は、複数の時間軸にまたがる膨大なデータを扱いながら取引戦略を構築しなければなりません。大量の指標に対してクエリを実行し、ほぼ瞬時に回答を得る必要があるでしょう。また、急変する市場に合わせてアルゴリズムや取引戦略を素早く適応させる必要もあります。Redis Enterpriseは、これらすべての課題に対応できるソリューションです。

最近、私はRedis Enterpriseが金融業界にとって不可欠なツールである理由について記事を執筆しました。本記事では、RedisTimeSeriesを使用して株価やテクニカル指標を保存・集計・クエリする方法をご紹介します。ここで解説する原則は、企業の財務情報や、ファンダメンタル投資家が利用するその他の時系列データの保存・照会にも応用できます。

RedisTimeSeriesモジュールは、数百万件のイベント、サンプル、価格データを取り込み、クエリすることが可能です。RedisTimeSeriesは、IoTからヘルスケア、金融まで幅広いユースケースにおいて、時刻と値のペアを関連付けて保存し、トレンドを把握するのに最適です。さらに、平均値、合計値、最小値、最大値、標準偏差、レンジ(範囲)などの集計機能を提供しており、データの分析と意思決定を容易に行えます。

RedisTimeSeriesによる株価トラッキング

本記事では、RedisTimeSeriesを使って株価とテクニカル指標を保存するモデルを紹介します。価格および指標に関する各種時系列の作成方法、生の時系列データ上に集計を作成する方法、そしてさまざまなRedisTimeSeriesコマンドを使って大量の時系列データをいかに簡単に取り込み・照会できるかをデモンストレーションします。また、ご自身のユースケースの出発点として活用できるPythonのサンプルコードも提供しています。

正しいかどうかはさておき、多くの人々はダウ工業株30種平均(DJIA)を米国経済の先行指標とみなしています。私はDJIA構成銘柄30社すべてのテクニカル指標に加え、株価と出来高をトラッキングしたいと考えました。まずは、ダウ構成銘柄であるゴールドマン・サックスの株価と、同銘柄のテクニカル指標の1つをトラッキングすることから始めます。私のお気に入りのテクニカル指標のひとつが相対力指数(RSI)です。RSIは、株式が買われ過ぎ(オーバーバought)か売られ過ぎ(オーバーソールド)の状態にあるかを測定するためのモメンタム系指標です。RSIが30付近または30を下回ると、その銘柄は売られ過ぎと判断され、買いのチャンスとなる可能性があります。逆に、RSIが70を超えると、買われ過ぎの領域に入りつつあり、売りどきのサインとなることがあります。

ゴールドマン・サックス・グループの相対力指数(RSI)

RedisTimeSeriesで金融アプリケーションを構築する方法:株価とテクニカル指標の時系列データ管理

取引時間中、RSIは他のテクニカル指標と同様に、ゴールドマン・サックス株の需要と供給に基づく売買が成立するたびに変動します。RedisTimeSeriesモジュールを活用すれば、次のような重要な質問に答えることができます。

  • 指定した時間間隔ごとのテクニカル指標の最小値と最大値はいくらか?
    • これにより、取引のエントリーポイントやエグジットポイントを素早く特定できます。
  • 指定した時間間隔における株価のレンジと標準偏差はいくらか?
    • レンジと標準偏差は、対象銘柄のボラティリティ(変動率)を示す指標です。
  • この銘柄の取引において、利益につながりそうなエントリー価格とエグジット価格はいくらか?
  • 指定した時間間隔における全銘柄のテクニカル指標の値はいくらか?

RedisTimeSeriesのクエリを使えば、指定した期間内のRSI最小値・最大値や株価をプログラム的に特定できます。たとえば、取引日の各15分間隔ごとのRSI最小値と最大値を知りたい場合はどうでしょうか。RSIが30付近になったときにアラートを発報したり、注文を出したり、あるいは売買の前に他のテクニカル指標を分析する複雑な取引ワークフローを起動したりすることも可能です。やりたいことは何でも、RedisTimeSeriesデータベースで簡単にモデル化できます。

株価とテクニカル指標のデータモデル

RedisTimeSeriesを手軽に体験する最も簡単な方法は、RedisTimeSeriesのDockerイメージを実行することです。

以下のコマンドを実行して、Dockerイメージを取得・起動します。

docker run -p 6379:6379 -it --rm redis/redistimeseries

Redisチームは、RedisTimeSeriesモジュールの設計において、「1つの時系列には1つのメトリックのみを保持する」という意図的な決定を行いました。このシンプルなデータモデルにより、データの挿入と取得が非常に高速になります。既存アプリケーションを壊す心配なく、必要に応じて新しい時系列を追加できます。つまり、データベーススキーマやアプリケーションを壊すことを気にせず、新しいデータソースを容易に追加できるのです。

RedisTimeSeriesコンテナが起動したら、Pythonを使ってサーバーに接続します(正しいIPアドレスまたはホスト名を指定してください)。

from redistimeseries.client import Client 
rts = Client(host='127.0.0.1', port=6379)

「1つの時系列に1つのメトリック」という設計原則に基づき、DJIA各銘柄の寄り付き間の株価とRSIを、それぞれ独立した時系列として保存できます。以下は、ゴールドマン・サックス・グループ(NYSE: GS)の時系列を作成した例です。ゴールドマン・サックスの日次RSIには 'DAILYRSI:GS' という名前を付け、各時系列にさまざまなラベルを適用しています。ラベルを付けておくと、ラベルをキーにすべてのキーを横断してクエリできるようになります。

rts.create('DAILYRSI:GS', 
            labels={ 'SYMBOL': 'GS'
                   , 'DESC':'RELATIVE_STRENGTH_INDEX'
                   , 'INDEX' :'DJIA'
                   , 'TIMEFRAME': '1_DAY'
                   , 'INDICATOR':'RSI'
                   , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'})

次に、ゴールドマン・サックスの寄り付き間の株価用に 'INTRADAYPRICES:GS' という時系列を作成します。

rts.create('INTRADAYPRICES:GS', 
            labels={ 'SYMBOL': 'GS'
                   , 'DESC':'SHARE_PRICE'
                   , 'INDEX' :'DJIA'
                   , 'PRICETYPE':'INTRADAY'
                   , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'})

続いて、RSIデータに対して15分間隔の各種集計を作成します(取引ニーズに応じて、より長い、あるいはより短い時間枠で集計を作成することも可能です)。これらの集計により、RSIの最初の値、最後の値、最小値、最大値、レンジを確認できます。集計を作成するには、まず集計結果を保存するための時系列を作成し、次にその時系列に集計値を投入するためのルールを作成します。ここでは、15分間のRSIレンジを保存するために 'DAILYRSI15MINRNG:GS' という時系列を作成しました。'createrule' は、生データ('DAILYRSI:GS')に対して15分ごとにrange関数を適用し、その結果を 'DAILYRSI15MINRNG:GS' に集約します。

rts.create('DAILYRSI15MINRNG:GS', 
            labels={ 'SYMBOL': 'GS' 
                   , 'DESC':'RELATIVE_STRENGTH_INDEX' 
                   , 'INDEX' :'DJIA' 
                   , 'TIMEFRAME': '15_MINUTES' 
                   , 'AGGREGATION': 'RANGE' 
                   , 'INDICATOR':'RSI' 
                   , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'}) 
rts.createrule('DAILYRSI:GS', 'DAILYRSI15MINRNG:GS', 'range', 900)

さらに、取引日の各15分間隔におけるゴールドマン・サックス株価のレンジと標準偏差を計算するためのルールを2つ作成します。

rts.create('INTRADAYPRICES15MINRNG:GS'
          , labels={ 'SYMBOL': 'GS'
                   , 'DESC':'SHARE_PRICE'
                   , 'INDEX' :'DJIA'
                   , 'PRICETYPE':'RANGE'
                   , 'AGGREGATION': 'RANGE'
                   , 'DURATION':'15_MINUTES'
                   , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'})

rts.createrule('INTRADAYPRICES:GS’
              ,'INTRADAYPRICES15MINRNG:GS'
              ,'range', 900)

rts.create('INTRADAYPRICES15MINSTDP:GS'
          , labels={ 'SYMBOL': 'GS'
                   , 'DESC':'SHARE_PRICE'
                   , 'INDEX' :'DJIA'
                   , 'PRICETYPE':'STDDEV'
                   , 'AGGREGATION': 'STDDEV'
                   , 'DURATION':'15_MINUTES'
                   , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'})

rts.createrule( 'INTRADAYPRICES:GS'
              , 'INTRADAYPRICES15MINSTDP:GS'
              , 'std.p', 900)

同じ要領で、ダウ工業株30種平均(DJIA)の全30銘柄分の時系列を作成できます。

データ取り込みの方法

RedisTimeSeriesにデータを取り込む方法は2つあります。TS.ADDコマンドを使うと、株価やテクニカル指標を1件ずつ時系列に追加できます。しかし、金融市場のデータはほぼ連続的に生成されるため、複数のサンプルをRedisTimeSeriesに追加する必要があります。そのような場合は、TS.MADDメソッドを使うのが効果的です。MADD関数はタプルのリストを引数に取ります。各タプルは、時系列キーの名前、タイムスタンプ、値で構成されます。

RedisTimeSeriesで金融アプリケーションを構築する方法:株価とテクニカル指標の時系列データ管理

以下のPythonコマンドで、時系列キーにデータを挿入できます。

rts.madd(<RSIIndicatorList>)

RedisTimeSeriesへのクエリ

RedisTimeSeriesでは、他の操作と同様に、データベースへのクエリも簡単に行えます。株価やテクニカル指標のレンジおよび標準偏差は、ボラティリティの指標となります。次のクエリを実行すると、ゴールドマン・サックス株価の15分ごとのレンジと標準偏差を確認できます。

rts.range( 'INTRADAYPRICES15MINRNG:GS' 
         , from_time = 1603704600 
         , to_time   = 1603713600)

このレンジ集計のクエリは、次のような結果セットを返します。

[(1603704600, 1.75999999999999), (1603705500, 0.775000000000006), (1603706400, 0.730000000000018), (1603707300, 0.449999999999989), (1603708200, 0.370000000000005), (1603709100, 1.01000000000002), (1603710000, 0.490000000000009), (1603710900, 0.89500000000001), (1603711800, 0.629999999999995), (1603712700, 0.490000000000009), (1603713600, 0.27000000000001)]

このクエリ結果を見ると、2020年10月26日(米東部時間)午前9時30分の取引開始時(整数タイムスタンプ=1603704600)、ゴールドマン・サックス株は変動が激しく、レンジは1.75ドルでした。これを、同日午前9時45分開始の次の15分間(整数タイムスタンプ=1603705500)と比較すると、ボラティリティは低下し、レンジは0.77ドルになっています。その後の15分間隔でもゴールドマン・サックス株の価格レンジは下落し続け、ボラティリティが寄り付き後15分間の水準に戻ることはありませんでした。

RedisTimeSeriesから取得したこのようなデータは、ダッシュボードやチャートで簡単に可視化できます。次のチャートは、ゴールドマン・サックスの15分間隔の価格レンジを示しています。

RedisTimeSeriesで金融アプリケーションを構築する方法:株価とテクニカル指標の時系列データ管理

次のチャートは、同じデータを折れ線グラフ形式で表示したもので、一日を通して時間が経過するにつれて、ゴールドマン・サックスの取引価格レンジが大きく収束していく様子がわかります(x軸は整数タイムスタンプを表示しています)。

RedisTimeSeriesで金融アプリケーションを構築する方法:株価とテクニカル指標の時系列データ管理

同様のクエリを、もう一つのボラティリティ指標である標準偏差を集計関数として実行することもできます。

rts.range( 'INTRADAYPRICES15MINSTDP:GS' 
         , from_time = 1603704600 
         , to_time   = 1603713600)
[(1603704600, 0.54657783830434), (1603705500, 0.23201149395202), (1603706400, 0.196072381345986), (1603707300, 0.160267138157647), (1603708200, 0.116990621700049), (1603709100, 0.28043101744222), (1603710000, 0.144379900126934), (1603710900, 0.327611558618967), (1603711800, 0.163118915546951), (1603712700, 0.151417199675549), (1603713600, 0.0963889432843203)]

ここから、興味深い可能性が広がります。たとえば「寄り付き間のRSI値が30〜40の間にあるとき、ゴールドマン・サックスの株価はいくらか」を知りたいとしましょう。RSIの時系列と株価の時系列をクエリすることで、利益につながるエントリーポイントを特定できます。

ここでは、1605260100(2020年11月13日 米東部時間 午前9時35分)から1605260940(同日午前9時49分)までの時間枠で、ゴールドマン・サックスのRSI値をクエリします。

dailyGSRSIValue = rts.range( 'DAILYRSI:GS'
                            , from_time = 1605260100
                            , to_time   = 1605260940)

クエリの結果、1605260820(米東部時間 午前9時47分)の時点でRSI値が34.2996427544861だったことがわかりました。

[(1605260100, 75.0305441024708), (1605260160, 81.6673948350152), (1605260220, 83.8852225932517), (1605260280, 85.9469082344746), (1605260340, 94.3803586011592), (1605260400, 92.2412262502652), (1605260460, 85.6867329371465), (1605260520, 87.9557361513823), (1605260580, 89.9407873066781), (1605260640, 57.1512452602676), (1605260700, 50.5638232111769), (1605260760, 35.2804436894564), (1605260820, 34.2996427544861), (1605260880, 54.5486275202972), (1605260940, 64.7593307385219)]

次に、RSIクエリと同じ時間枠でゴールドマン・サックスの寄り付き間株価をクエリするか、プログラムでクエリを変更して、RSI値が34.29だった時点を反映させることができます。以下は、RSIクエリと同じ時間枠を使用した例です。

dailyGSPrice = rts.range( 'INTRADAYPRICES:GS'
                         , from_time = 1605260100
                         , to_time   = 1605260940)

クエリは、指定された範囲のゴールドマン・サックス株価を返します。1605260820(2020年11月13日 米東部時間 午前9時47分)の時点で、株価は217.18ドルでした。

[(1605260100, 216.57), (1605260160, 216.73), (1605260220, 217.08), (1605260280, 217.17), (1605260340, 217.87), (1605260400, 218.05), (1605260460, 217.91), (1605260520, 218.0), (1605260580, 218.11), (1605260640, 218.02), (1605260700, 217.72), (1605260760, 217.22), (1605260820, 217.18), (1605260880, 217.46), (1605260940, 217.61)]

RedisTimeSeriesは、複数の時系列を一度に横断してクエリする強力な手段を提供します。TS.MGETコマンドを使うと、フィルターを指定して複数の時系列を横断的にクエリできます。すでにさまざまな時系列を作成し、それぞれにラベルを付与済みなので、これらのラベルをフィルターとして使い、時系列全体を横断したクエリが可能です。

次のPythonコードは、「DESC」と「TIMEFRAME」という2つのラベルに基づくフィルターを適用しています。パラメータ "with_labels=False" を指定すると、各値のラベルを含まない結果セットが返されます。

allRSIValues = rts.mget(filters=['DESC=RELATIVE_STRENGTH_INDEX','TIMEFRAME=1_DAY'], with_labels=False)

このクエリは、複数銘柄の最新RSI値を返す、以下のような結果を表示します。

[{'DAILYRSI:BA': [{}, 1605261060, 62.2048922111768]}, {'DAILYRSI:CAT': [{}, 1605261060, 68.3834400302296]}, {'DAILYRSI:CRM': [{}, 1605261060, 59.2107333830133]}, {'DAILYRSI:CSCO': [{}, 1605261060, 52.7011052724688]}, {'DAILYRSI:CVX': [{}, 1605261060, 62.9890368832232]}, {'DAILYRSI:DOW': [{}, 1605261060, 73.597680480764]}, {'DAILYRSI:GS': [{}, 1605283140, 41.182852552541]}, {'DAILYRSI:IBM': [{}, 1605261060, 65.3742140862697]}, {'DAILYRSI:JPM': [{}, 1605261060, 77.7760292843745]}, {'DAILYRSI:KO': [{}, 1605261060, 26.8638381005608]}, {'DAILYRSI:MMM': [{}, 1605261060, 65.7852833683174]}, {'DAILYRSI:MRK': [{}, 1605261060, 38.9991886598036]}, {'DAILYRSI:UNH': [{}, 1605261060, 74.2672428885775]}, {'DAILYRSI:VZ': [{}, 1605261060, 33.177554436462]}, {'DAILYRSI:WBA': [{}, 1605261060, 47.3877762365391]}]

もし "with_labels=True" を設定していれば、結果には以下のように各時系列に付けられたすべてのラベルが含まれます。

[{'DAILYRSI:BA': [{'SYMBOL': 'BA', 'DESC': 'RELATIVE_STRENGTH_INDEX', 'INDEX': 'DJIA', 'TIMEFRAME': '1_DAY', 'INDICATOR': 'RSI', 'COMPANYNAME': 'BOEING'}, 1605261060, 62.2048922111768]}, {'DAILYRSI:CAT': [{'SYMBOL': 'CAT', 'DESC': 'RELATIVE_STRENGTH_INDEX', 'INDEX': 'DJIA', 'TIMEFRAME': '1_DAY', 'INDICATOR': 'RSI', 'COMPANYNAME': 'CATERPILLAR'}, 1605261060, 68.3834400302296]}, {'DAILYRSI:CRM': [{'SYMBOL': 'CRM', 'DESC': 'RELATIVE_STRENGTH_INDEX', 'INDEX': 'DJIA', 'TIMEFRAME': '1_DAY', 'INDICATOR': 'RSI', 'COMPANYNAME': 'SALESFORCE'}, 1605261060, 59.2107333830133]}]

まとめ

本記事では、時系列データに依存する金融アプリケーションを柔軟に構築するための、RedisTimeSeriesの豊富なコマンドの一部をご紹介しました。たとえば株式トレーダーは、数十の変数に基づいてリアルタイムで重大な意思決定を下す必要があります。RedisTimeSeriesはスキーマレスであるため、スキーマを定義せずにデータを読み込んだり、その場で新しいフィールドを追加したり、ビジネス環境の変化に応じてデータモデルを変更したりすることが可能です。リアルタイム性能と開発者にとってシンプルな操作性により、時系列データを扱う作業が楽しくなるでしょう。

本記事のサンプルコードはGitHubで公開されています。また、RedisTimeSeriesの詳細については公式ドキュメントをご覧ください。

  1. RedisTimeSeries 1.6正式リリース!新機能と性能改善を徹底解説

    本日、RedisTimeSeries 1.6の一般提供(GA)開始をお知らせできることを嬉しく思います。この記事では、新たに利用可能になった主要な新機能について詳しく紹介します。 RedisTimeSeriesとは RedisTimeSeriesは、Redis向けの高性能なメモリファースト型の時系列データ構造です。マルチテナンシー(多数の時系列を同時に保持できる)に対応しており、複数のクライアントがこれらの時系列へ同時にアクセスすることも可能です。現在では、Redis Stackの一部としても提供されています。 RedisTimeSeries 1.6の主な新機能 クエリ機能の強化

  2. PCでiOSアプリを実行する方法|おすすめiOSエミュレーター10選

    iPhoneは性能が高い一方で価格も高く、「手が出せない」と感じている方は少なくありません。iPhoneには魅力的なアプリが数多くありますが、本体を持っていなければその魅力を味わえないのが現状です。しかし、実はPCに「iOSエミュレーター」を導入すれば、iPhoneを購入しなくてもiOSアプリを体験できるのです。エミュレーターを使えば、大きめの画面でiOSアプリを操作でき、多くのツールが無料で利用可能です。この記事では、PCでiOSアプリを動かすためのおすすめエミュレーターを厳選してご紹介します。各ツールのダウンロードリンクも記載しているので、自分に合ったものを見つけてぜひ試してみてください。