Skip to content
namba3Public

About

A no_std-compatible Rust library for technical analysis indicators, with composable operators and iterator and stream adapters.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

Indicator

English | 日本語

テクニカル分析で使うインジケーターを実装した Rust ライブラリです。

金融商品におけるテクニカル分析

テクニカル分析は、株式・為替・先物などの金融商品の価格や出来高の時系列を調べ、市場のトレンドや勢い、変動の大きさを把握する手法です。インジケーターは、こうした時系列を特定の計算方法と期間で要約します。

  • トレンド: SMA、EMA、RMA、Aroon
  • モメンタム: RSI、MACD、Stochastics
  • 価格変動・レンジ: Bollinger Bands、Standard Deviation、Max、Min
  • 出来高: VWAP、VWMA

同じインジケーターでも、入力する価格・出来高、観測間隔、計算期間によって値は変わります。指標の値や過去のパターンだけで将来の値動きが決まるわけではなく、シグナルが外れることもあります。頻繁な売買を伴う場合は、手数料などの取引コストや、売買タイミングを逃すリスクも考慮してください。

このライブラリは指標の値を計算します。市場データの取得、売買シグナルの評価、投資判断や注文は行いません。投資には損失のリスクがあります。

参考: CFA Institute Research Foundation: Technical Analysis: Modern Perspectives、FINRA: What Is Market Timing?、Investor.gov: What Is Risk?

使用例

use indicator::*;

fn main() {
    use std::f64::consts::PI;

    let mut sma = Sma::new(5).unwrap();

    for input in (0..100).map(|n| f64::sin(PI / 10.0 * n as f64)) {
        let value: f64 = sma.next(input);
        println!("{value}");
    }
}

実装済みのインジケーター

  • Aroon Indicator
  • Aroon Oscillator
  • Bollinger Bands(BollingerBands)
  • EMA: Exponential Moving Average
  • MACD: Moving Average Convergence Divergence
  • Max
  • Max Index(最高値からの経過サンプル数)
  • Min Index(最安値からの経過サンプル数)
  • Min
  • RMA: Running Moving Average(Modified Moving Average とも呼ばれます)
  • RSI: Relative Strength Index
  • SMA: Simple Moving Average
  • Standard Deviation
  • Stochastics
  • VWAP: Volume Weighted Average Price
  • VWMA: Volume Weighted Moving Average

初期値とウォームアップ

特に記載がない指標は、最初の入力から next が値を返します。期間分の入力がそろうまで待つ挙動ではありません。期間を指定する指標の初期化と出力範囲は次のとおりです。

指標 初期化と最初の出力 出力範囲・性質
SMA、Standard Deviation、Bollinger Bands、Max、Min 最初の入力を窓全体に複製し、初回から出力します。 SMA・平均・極値は入力と同じ尺度です。標準偏差は 0 以上、Bollinger Bands は lower_bound <= average <= upper_bound です。
Max Index、Min Index 最初の入力を窓全体に複製し、初回から出力します。 極値からの経過サンプル数で、0..period(period は含みません)です。
EMA、RMA 最初の入力を初期値にし、初回から出力します。EMA は 2 / (period + 1)、RMA は 1 / period の係数で更新します。 入力と同じ尺度です。
RSI 初回の変化量を 0 として扱い、初回は 0.5 を返します。 0..=1 です。
MACD 短期・長期 EMA は最初の入力から始まるため、初回は MACD、Signal、Histogram がすべて 0 です。 固定範囲はありません。
Stochastics 初回は %K、%D、Slow %D がすべて 0.5 です。分母が 0 の場合も 0.5 を使います。 3つとも 0..=1 です。
Aroon Indicator、Aroon Oscillator 初回入力で窓を埋め、初回から出力します。Aroon Up/Down は初回 1、Oscillator は初回 0 です。 Aroon Up/Down は 0..=1、Oscillator は -1..=1 です。
VWAP 累積出来高が初めて正になった入力から値を返します。正の出来高がない間、current() と next_option() は None、通常の next() は NaN です。 正の出来高を持つ価格の加重平均です。
VWMA 最初の価格・出来高の組を窓全体に複製します。窓内の合計出来高が正になった時点から値を返します。 窓内で正の出来高を持つ価格の加重平均です。

mature(n) を組み合わせると、先頭の n 個の出力を None にし、n + 1 個目から値を返せます。指標本体の初期化規則は変わらず、出力を見せ始める時点だけが遅れます。

機能

インジケーターの出力を変換する

出力に関数を適用できます。

use std::f64::consts::PI;

let macd = Macd::default();
let mut macd = macd.map(|MacdOutput{ macd, signal: _, histogram: _}| macd);

for input in (0..100).map(|n| f64::sin(PI / 10.0 * n as f64)) {
    let value: f64 = macd.next(input);
    println!("{value}");
}

インジケーターを合成する

あるインジケーターの出力を、別のインジケーターへの入力として使えます。

use std::f64::consts::PI;

let sma = Sma::new(2).unwrap();
let rsi = Rsi::new(14).unwrap();

let mut sma_against_rsi = rsi.pushforward(sma);

for input in (0..100).map(|n| f64::sin(PI / 10.0 * n as f64)) {
    let value: f64 = sma_against_rsi.next(input);
    println!("{value}");
}

成熟前の値を除外する

計算に必要なデータが十分に蓄積されるまで、出力を None にできます。

let sma = Sma::new(4).unwrap();
let mut sma = sma.mature(3);

assert_eq!(sma.next(1.0), None);
assert_eq!(sma.next(2.0), None);
assert_eq!(sma.next(1.0), None);
assert_eq!(sma.next(2.0), Some(1.5));
assert_eq!(sma.next(1.0), Some(1.5));
assert_eq!(sma.next(2.0), Some(1.5));

出力をウィンドウで取得する

内部インジケーターの直近 N 個の出力をまとめて取得できます。

let sma = Sma::new(5).unwrap();
let mut sma_window = sma.window(3);

assert_eq!(sma_window.next(100.0), vec![100.0, 100.0, 100.0]);
assert_eq!(sma_window.next(101.0), vec![100.0, 100.0, 100.2]);
assert_eq!(sma_window.next(101.0), vec![100.0, 100.2, 100.4]);
assert_eq!(sma_window.next(102.0), vec![100.2, 100.4, 100.8]);
assert_eq!(sma_window.next(102.0), vec![100.4, 100.8, 101.2]);
assert_eq!(sma_window.next(102.0), vec![100.8, 101.2, 101.6]);

スナップショットが不要な場合は advance と iter を使うと、ウィンドウの読み取り用 Vec を作らずに更新できます。

let sma = Sma::new(5).unwrap();
let mut sma_window = sma.window(3);

sma_window.advance(100.0);
assert_eq!(sma_window.iter().copied().collect::<Vec<_>>(), vec![100.0, 100.0, 100.0]);

出来高 0 の加重平均を扱う

VWAP と VWMA の next_option は、合計出来高が 0 の間 None を返します。既存の Next は f64 の戻り値を保ち、計算結果が未定義の間は NaN を返します。

NaN・無限大の価格、および負数・NaN・無限大の出来高は無効です。負の有限価格は有効です。try_next(タプル入力)または try_next_ref(Price と Volume を実装した型の参照)を使うと、InvalidPrice または InvalidVolume エラーになり、指標の状態は変化しません。既存の Next は戻り値の型を変えず、不正な入力を無視して現在値を返します(有効な値がまだない場合は NaN)。外部データを検証する場合は try_next 系を使用してください。

let mut vwap = Vwap::new();

assert_eq!(vwap.next_option((100.0, 0.0)), None);
assert_eq!(vwap.next_option((110.0, 2.0)), Some(110.0));
assert!(vwap.try_next((120.0, -1.0)).is_err());

Iterator に変換する

入力値の Iterator から、インジケーターの出力を生成する Iterator を作れます。

use std::f64::consts::PI;

let sma = Sma::new(2).unwrap();

let input_iter = (0..100).map(|n| f64::sin(PI / 10.0 * n as f64));
let mut sma_iter = sma.iter_over(input_iter);

while let Some(value) = sma_iter.next() {
    println!("{value}");
}

Stream に変換する

入力 Stream から、インジケーターの出力を生成する Stream を作れます。この機能を使うには stream feature を有効にしてください。

use futures_util::{stream, StreamExt};
use std::f64::consts::PI;

let sma = Sma::new(2).unwrap();

let input_iter = (0..100).map(|n| f64::sin(PI / 10.0 * n as f64));
let input_stream = stream::iter(input_iter);
let mut sma_stream = sma.iter_over_stream(input_stream);

while let Some(value) = sma_stream.next().await {
    println!("{value}");
}

ベンチマーク

stable Rust の std::time::Instant と std::hint::black_box を使ったベンチマークを実行できます。

cargo bench --bench indicators
cargo bench --bench indicators -- 2000000

数値は実行環境に依存します。異なる環境間の性能比較には使わず、同じ環境での相対比較に利用してください。

ライセンス

このプロジェクトは MIT または Apache License 2.0 のいずれかの条件で利用できます。MIT ライセンスの著作権者は GitHub ユーザー @namba3 です。

About

A no_std-compatible Rust library for technical analysis indicators, with composable operators and iterator and stream adapters.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages