chart/app/analysis/indicators.py

40 lines
1.3 KiB
Python

from app.bars.models import Bar
def sma(values: list[float], period: int) -> list[float | None]:
if period <= 0:
raise ValueError("period must be positive")
output: list[float | None] = [None] * len(values)
total = 0.0
for index, value in enumerate(values):
total += value
if index >= period:
total -= values[index - period]
if index >= period - 1:
output[index] = total / period
return output
def ema(values: list[float], period: int) -> list[float | None]:
if period <= 0:
raise ValueError("period must be positive")
output: list[float | None] = [None] * len(values)
if len(values) < period:
return output
value = sum(values[:period]) / period
output[period - 1] = value
multiplier = 2 / (period + 1)
for index in range(period, len(values)):
value = (values[index] - value) * multiplier + value
output[index] = value
return output
def atr(bars: list[Bar], period: int = 14) -> list[float | None]:
if period <= 0:
raise ValueError("period must be positive")
ranges: list[float] = []
for index, bar in enumerate(bars):
previous_close = bars[index - 1].c if index else bar.c
ranges.append(max(bar.h - bar.l, abs(bar.h - previous_close), abs(bar.l - previous_close)))
return sma(ranges, period)