module Signals

frozen_string_literal: true

Public Instance Methods

bollinger_bands(data, pivot = [0, 1, 2]) { |data| ... } click to toggle source

ボリンジャーバンドを計算します。

+2σ=移動平均+標準偏差×2
+σ=移動平均+標準偏差
-σ=移動平均-標準偏差
-2σ=移動平均-標準偏差×2
標準偏差=√((各値-値の期間中平均値)の2乗を期間分全部加えたもの)/ 期間
(√は式全体にかかる)
data

値の配列

pivot

標準偏差の倍数。初期値 [0,1,2]

block

移動平均を算出するロジック。指定がなければ移動平均を使う。

戻り値

ボリンジャーバンドの各値の配列。例) [+2σ, +1σ, TP, -1σ, -2σ]

# File src/jiji/model/agents/builtin_files/signals.rb, line 277
def bollinger_bands(data, pivot = [0, 1, 2], &block)
  ma = block_given? ? yield(data) : ma(data)
  sd = standard_division(data) { |s| s - ma }
  pivot.each_with_object([]) do |r, res|
    res.unshift(ma + sd * r)
    res.push(ma + sd * r * -1) if r.nonzero?
  end
end
dmi(data) click to toggle source

DMIを計算します。

高値更新  ...  前日高値より当日高値が高かった時その差
安値更新  ...  前日安値より当日安値が安かった時その差
DM        ...  高値更新が安値更新より大きかった時高値更新の値。逆の場合は0
DM        ...  安値更新が高値更新より大きかった時安値更新の値。逆の場合は0
TR        ...  次の3つの中で一番大きいもの
                当日高値-当日安値
                当日高値-前日終値
                前日終値-当日安値
AV(+DM)   ...  +DMのn日間移動平均値
AV(-DM)   ...  -DMのn日間移動平均値
AV(TR)    ...  TRのn日間移動平均値
+DI       ...  AV(+DM)/AV(TR)
-DI       ...  AV(-DM)/AV(TR)
DX        ...  (+DIと-DIの差額) / (+DIと-DIの合計)
ADX       ...  DXのn日平均値
data

値の配列(4本値を指定すること!) 例: {open: 123.2, close: 124, high: 124.2, low: 123}

戻り値

{:pdi=pdi, :mdi=mdi, :dx=dx }

# File src/jiji/model/agents/builtin_files/signals.rb, line 362
def dmi(data)
  tmp = calculate_dmi_from_data(data)
  atr = ma(tmp[0])
  pdi = ma(tmp[1]) / atr * 100
  mdi = ma(tmp[2]) / atr * 100
  { pdi: pdi, mdi: mdi, dx: calculate_dx(pdi, mdi) }
end
ema(data, smoothing_coefficient = 0.1) click to toggle source

指数移動平均値を計算します。

data

値の配列。

smoothing_coefficient

平滑化係数

戻り値

加重移動平均値

# File src/jiji/model/agents/builtin_files/signals.rb, line 258
def ema(data, smoothing_coefficient = 0.1)
  data[1..-1].reduce(data[0]) do |t, s|
    t + smoothing_coefficient * (s - t)
  end
end
ma(data) click to toggle source

移動平均値を計算します。

data

値の配列。

戻り値

移動平均値

# File src/jiji/model/agents/builtin_files/signals.rb, line 236
def ma(data)
  total = data.reduce(:+)
  total / data.length
end
macd(data, short_range, long_range, smoothing_coefficient) click to toggle source

MACDを計算します。

MACD = 短期(short_range日)の指数移動平均 - 長期(long_range日)の指数移動平均
data

値の配列

smoothing_coefficient

平滑化係数

戻り値

macd値

# File src/jiji/model/agents/builtin_files/signals.rb, line 319
def macd(data, short_range, long_range, smoothing_coefficient)
  ema(data[short_range * -1..-1], smoothing_coefficient)        - ema(data[long_range * -1..-1], smoothing_coefficient)
end
momentum(data) click to toggle source

一定期間の値の傾きを計算します。

data

値の配列

戻り値

傾き。0より大きければ上向き。小さければ下向き。

# File src/jiji/model/agents/builtin_files/signals.rb, line 290
def momentum(data)
  (data.last - data.first) / data.length
end
roc(data) click to toggle source

ROCを計算します。

ROC = Rate of Change。変化率。正なら上げトレンド、負なら下げトレンド。
data

値の配列

戻り値

# File src/jiji/model/agents/builtin_files/signals.rb, line 376
def roc(data)
  (data.first - data.last) / data.last * 100
end
rsi(data) click to toggle source

RSIを計算します。

RSI =
 n日間の値上がり幅合計 / (n日間の値上がり幅合計 + n日間の値下がり幅合計) * 100
nとして、14や9を使うのが、一般的。30以下では売られすぎ70以上では買われすぎの水準
data

値の配列

戻り値

RSI値

# File src/jiji/model/agents/builtin_files/signals.rb, line 332
def rsi(data)
  prev = nil
  tmp = data.each_with_object([0.0, 0.0]) do |i, r|
    r[i > prev ? 0 : 1] += (i - prev).abs if prev
    prev = i
  end
  calculate_rsi(tmp)
end
vector(data) click to toggle source

最小二乗法で、一定期間の値の傾きを計算します。

data

値の配列

戻り値

傾き。0より大きければ上向き。小さければ下向き。

# File src/jiji/model/agents/builtin_files/signals.rb, line 298
def vector(data)
  # 最小二乗法を使う。
  total = { x: 0.0, y: 0.0, xx: 0.0, xy: 0.0, yy: 0.0 }
  data.each_index do |i|
    v = data[i]
    total[:x] += i
    total[:y] += v
    total[:xx] += i * i
    total[:xy] += i * v
    total[:yy] += v * v
  end
  calculate_vector(data, total)
end
wma(data) click to toggle source

加重移動平均値を計算します。

data

値の配列。

戻り値

加重移動平均値

# File src/jiji/model/agents/builtin_files/signals.rb, line 245
def wma(data)
  weight = 0
  total = data.reduce(0.0) do |t, s|
    t + s * (weight += 1)
  end
  total / (data.length * (data.length + 1) / 2)
end