40 lines
1.3 KiB
Python
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)
|