Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Aroon Oscillator and change in SMA docstring. #20

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Accumulation/Distribution
Aroon
-Aroon Up
-Aroon Down
-Aroon Oscillator
Average Directional Index
Average True Range
Average True Range Percent
Expand Down
21 changes: 14 additions & 7 deletions pyti/accumulation_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ def accumulation_distribution(close_data, high_data, low_data, volume):

ad = np.zeros(len(close_data))
for idx in range(1, len(close_data)):
ad[idx] = (
(((close_data[idx] - low_data[idx]) -
(high_data[idx] - close_data[idx])) /
(high_data[idx] - low_data[idx]) *
volume[idx]) +
ad[idx-1]
)
candle = high_data[idx] - low_data[idx]
if candle == 0:
if high_data[idx] != close_data[idx]:
raise RuntimeError("High and low are equals but close is not.")
else:
ad[idx] = ad[idx - 1]
else:
ad[idx] = (
(((close_data[idx] - low_data[idx]) -
(high_data[idx] - close_data[idx])) /
(high_data[idx] - low_data[idx]) *
volume[idx]) +
ad[idx-1]
)
return ad
12 changes: 12 additions & 0 deletions pyti/aroon.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,15 @@ def aroon_down(data, period):
float(period)) * 100 for idx in range(period-1, len(data))]
a_down = fill_for_noncomputable_vals(data, a_down)
return a_down


def aroon_oscillator(data, period):
"""
Aroon Oscillator.

Formula:
AO = AROON_UP(PERIOD) - AROON_DOWN(PERIOD)
"""
catch_errors.check_for_period_error(data, period)
period = int(period)
return aroon_up(data, period) - aroon_down(data, period)
19 changes: 19 additions & 0 deletions pyti/force_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from __future__ import absolute_import
from pyti import catch_errors
import numpy as np


def force_index(close_data, volume):
"""
Force Index.

Formula:
"""
catch_errors.check_for_input_len_diff(
close_data, volume
)

pc = np.diff(close_data, 1)
fi = pc * volume[1:]
fi = np.append(np.nan, fi)
return fi
7 changes: 2 additions & 5 deletions pyti/relative_strength_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@ def relative_strength_index(data, period):
period = int(period)
changes = [data_tup[1] - data_tup[0] for data_tup in zip(data[::1], data[1::1])]

filtered_gain = [val < 0 for val in changes]
gains = [0 if filtered_gain[idx] is True else changes[idx] for idx in range(0, len(filtered_gain))]

filtered_loss = [val > 0 for val in changes]
losses = [0 if filtered_loss[idx] is True else abs(changes[idx]) for idx in range(0, len(filtered_loss))]
gains = [0 if val < 0 else val for val in changes]
losses = [0 if val > 0 else abs(val) for val in changes]

avg_gain = np.mean(gains[:period])
avg_loss = np.mean(losses[:period])
Expand Down
2 changes: 1 addition & 1 deletion pyti/simple_moving_average.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def simple_moving_average(data, period):
Simple Moving Average.

Formula:
SUM(data / N)
SUM(data) / N
"""
catch_errors.check_for_period_error(data, period)
# Mean of Empty Slice RuntimeWarning doesn't affect output so it is
Expand Down
41 changes: 41 additions & 0 deletions pyti/true_strength_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.function_helper import fill_for_noncomputable_vals
from pyti.exponential_moving_average import (
exponential_moving_average as ema
)


def true_strength_index(close_data):
"""
True Strength Index.

Double Smoothed PC
------------------
PC = Current Price minus Prior Price
First Smoothing = 25-period EMA of PC
Second Smoothing = 13-period EMA of 25-period EMA of PC

Double Smoothed Absolute PC
---------------------------
Absolute Price Change |PC| = Absolute Value of Current Price minus Prior Price
First Smoothing = 25-period EMA of |PC|
Second Smoothing = 13-period EMA of 25-period EMA of |PC|

TSI = 100 x (Double Smoothed PC / Double Smoothed Absolute PC)
"""
if len(close_data) < 40:
raise RuntimeError("Data must have at least 40 items")

pc = np.diff(close_data, 1)
apc = np.abs(pc)

num = ema(pc, 25)
num = ema(num, 13)
den = ema(apc, 25)
den = ema(den, 13)

tsi = 100 * num / den
tsi = fill_for_noncomputable_vals(close_data, tsi)
return tsi