Skip to content

Commit

Permalink
Merge pull request #6 from kylejusticemagnuson/python-3-upgrade
Browse files Browse the repository at this point in the history
Python 3 upgrade
  • Loading branch information
Kyle Magnuson authored Nov 30, 2017
2 parents 18a49b3 + 0b61b8c commit ffe741a
Show file tree
Hide file tree
Showing 96 changed files with 316 additions and 304 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ dist/
__pycache__/
*.so
*~
.vscode

# due to using tox and pytest
.tox
.cache
.bak
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This library contains various financial technical indicators that can be used to analyze data.

Now compatible with both Python 2.7 and Python 3.6

The complete list of indicators in this library:
```
Accumulation/Distribution
Expand Down Expand Up @@ -81,7 +83,6 @@ Volume Oscillator
Weighted Moving Average
Williams %R
```
pyti is currently only compatible with Python 2.7

Install using pip:
```
Expand All @@ -99,5 +100,24 @@ res = ema(data, period)
# res = [np.nan, 6.75, 4.0, 5.25, 3.75, 7.5, 6.0]
```

Running the whole test suite using tox:
```
tox
```

To run tests for just Python 2.7 use
```
tox -e py27 tests
```
or just for Python 3.6
```
tox -e py36 tests
```

To specifically run one test in a specific Python version:
```
tox -e py36 -- tests/test_file_you_want_to_test:TestClassName.test_method_name
```

If there is an indicator that you would like to see added or believe there is an error in one of the existing ones, feel free to submit it to Issues.
If you would like to add your own indicator, fork the project and submit a pull request. Contributions are always welcome.
2 changes: 2 additions & 0 deletions pyti/accumulation_distribution.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from six.moves import range


def accumulation_distribution(close_data, high_data, low_data, volume):
Expand Down
25 changes: 10 additions & 15 deletions pyti/aroon.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.function_helper import fill_for_noncomputable_vals
from six.moves import range


def aroon_up(data, period):
Expand All @@ -13,15 +15,11 @@ def aroon_up(data, period):
catch_errors.check_for_period_error(data, period)
period = int(period)

aroon_up = map(
lambda idx:
((period -
a_up = [((period -
data[idx+1-period:idx+1].index(np.max(data[idx+1-period:idx+1]))) /
period) * 100,
range(period-1, len(data))
)
aroon_up = fill_for_noncomputable_vals(data, aroon_up)
return aroon_up
float(period)) * 100 for idx in range(period-1, len(data))]
a_up = fill_for_noncomputable_vals(data, a_up)
return a_up


def aroon_down(data, period):
Expand All @@ -34,11 +32,8 @@ def aroon_down(data, period):
catch_errors.check_for_period_error(data, period)
period = int(period)

aroon_down = map(
lambda idx:
((period -
a_down = [((period -
data[idx+1-period:idx+1].index(np.min(data[idx+1-period:idx+1]))) /
period) * 100,
range(period-1, len(data)))
aroon_down = fill_for_noncomputable_vals(data, aroon_down)
return aroon_down
float(period)) * 100 for idx in range(period-1, len(data))]
a_down = fill_for_noncomputable_vals(data, a_down)
return a_down
2 changes: 2 additions & 0 deletions pyti/average_true_range.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import absolute_import
import numpy as np
from pyti.true_range import true_range
from six.moves import range


def average_true_range(close_data, period):
Expand Down
1 change: 1 addition & 0 deletions pyti/average_true_range_percent.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.average_true_range import (
Expand Down
2 changes: 2 additions & 0 deletions pyti/bollinger_bands.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
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.simple_moving_average import (
simple_moving_average as sma
)
from six.moves import range


def upper_bollinger_band(data, period, std_mult=2.0):
Expand Down
2 changes: 1 addition & 1 deletion pyti/catch_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def check_for_input_len_diff(*args):
message that informs the developer that the data set's lengths are not the
same.
"""
arrays_len = map(lambda arr: len(arr), args)
arrays_len = [len(arr) for arr in args]
if not all(a == arrays_len[0] for a in arrays_len):
err_msg = ("Error: mismatched data lengths, check to ensure that all "
"input data is the same length and valid")
Expand Down
10 changes: 4 additions & 6 deletions pyti/chaikin_money_flow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.function_helper import fill_for_noncomputable_vals
from six.moves import range


def chaikin_money_flow(close_data, high_data, low_data, volume, period):
Expand All @@ -18,13 +20,9 @@ def chaikin_money_flow(close_data, high_data, low_data, volume, period):
high_data = np.array(high_data)
low_data = np.array(low_data)
volume = np.array(volume)
cmf = map(
lambda idx:
sum((((close_data[idx+1-period:idx+1] - low_data[idx+1-period:idx+1]) -
cmf = [sum((((close_data[idx+1-period:idx+1] - low_data[idx+1-period:idx+1]) -
(high_data[idx+1-period:idx+1] - close_data[idx+1-period:idx+1])) /
(high_data[idx+1-period:idx+1] - low_data[idx+1-period:idx+1])) *
volume[idx+1-period:idx+1]) / sum(volume[idx+1-period:idx+1]),
range(period-1, len(close_data))
)
volume[idx+1-period:idx+1]) / sum(volume[idx+1-period:idx+1]) for idx in range(period-1, len(close_data))]
cmf = fill_for_noncomputable_vals(close_data, cmf)
return cmf
16 changes: 6 additions & 10 deletions pyti/chande_momentum_oscillator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import absolute_import
import numpy as np
import warnings
from pyti import catch_errors
from six.moves import range


def chande_momentum_oscillator(close_data, period):
Expand All @@ -14,21 +16,15 @@ def chande_momentum_oscillator(close_data, period):

close_data = np.array(close_data)

moving_period_diffs = map(
lambda idx:
map(lambda i:
(close_data[idx+1-period:idx+1][i] -
close_data[idx+1-period:idx+1][i-1]),
range(1, len(close_data[idx+1-period:idx+1]))),
range(0, len(close_data))
)
moving_period_diffs = [[(close_data[idx+1-period:idx+1][i] -
close_data[idx+1-period:idx+1][i-1]) for i in range(1, len(close_data[idx+1-period:idx+1]))] for idx in range(0, len(close_data))]

sum_up = []
sum_down = []
for period_diffs in moving_period_diffs:
ups = map(lambda val: val if val > 0 else 0, period_diffs)
ups = [val if val > 0 else 0 for val in period_diffs]
sum_up.append(sum(ups))
downs = map(lambda val: abs(val) if val < 0 else 0, period_diffs)
downs = [abs(val) if val < 0 else 0 for val in period_diffs]
sum_down.append(sum(downs))

sum_up = np.array(sum_up)
Expand Down
1 change: 1 addition & 0 deletions pyti/commodity_channel_index.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.typical_price import typical_price
Expand Down
8 changes: 3 additions & 5 deletions pyti/detrended_price_oscillator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.function_helper import fill_for_noncomputable_vals
from six.moves import range


def detrended_price_oscillator(data, period):
Expand All @@ -12,10 +14,6 @@ def detrended_price_oscillator(data, period):
"""
catch_errors.check_for_period_error(data, period)
period = int(period)
dop = map(
lambda idx:
data[idx] - np.mean(data[idx+1-((period/2)+1):idx+1]),
range(period-1, len(data))
)
dop = [data[idx] - np.mean(data[idx+1-(int(period/2)+1):idx+1]) for idx in range(period-1, len(data))]
dop = fill_for_noncomputable_vals(data, dop)
return dop
12 changes: 4 additions & 8 deletions pyti/directional_indicators.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.smoothed_moving_average import (
Expand All @@ -6,6 +7,7 @@
from pyti.average_true_range import (
average_true_range as atr
)
from six.moves import range


def calculate_up_moves(high_data):
Expand All @@ -15,10 +17,7 @@ def calculate_up_moves(high_data):
Formula:
UPMOVE = Ht - Ht-1
"""
up_moves = map(
lambda idx: high_data[idx] - high_data[idx-1],
range(1, len(high_data))
)
up_moves = [high_data[idx] - high_data[idx-1] for idx in range(1, len(high_data))]
return [np.nan] + up_moves


Expand All @@ -29,10 +28,7 @@ def calculate_down_moves(low_data):
Formula:
DWNMOVE = Lt-1 - Lt
"""
down_moves = map(
lambda idx: low_data[idx-1] - low_data[idx],
range(1, len(low_data))
)
down_moves = [low_data[idx-1] - low_data[idx] for idx in range(1, len(low_data))]
return [np.nan] + down_moves


Expand Down
1 change: 1 addition & 0 deletions pyti/double_exponential_moving_average.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
from pyti import catch_errors
from pyti.exponential_moving_average import (
exponential_moving_average as ema
Expand Down
14 changes: 4 additions & 10 deletions pyti/double_smoothed_stochastic.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
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
)
from six.moves import range


def double_smoothed_stochastic(data, period):
Expand All @@ -14,17 +16,9 @@ def double_smoothed_stochastic(data, period):
dss = 100 * EMA(Close - Lowest Low) / EMA(Highest High - Lowest Low)
"""
catch_errors.check_for_period_error(data, period)
lows = map(
lambda idx:
data[idx] - np.min(data[idx+1-period:idx+1]),
range(period-1, len(data))
)
lows = [data[idx] - np.min(data[idx+1-period:idx+1]) for idx in range(period-1, len(data))]
sm_lows = ema(ema(lows, period), period)
highs = map(
lambda idx:
np.max(data[idx+1-period:idx+1]) - np.min(data[idx+1-period:idx+1]),
range(period-1, len(data))
)
highs = [np.max(data[idx+1-period:idx+1]) - np.min(data[idx+1-period:idx+1]) for idx in range(period-1, len(data))]
sm_highs = ema(ema(highs, period), period)
dss = (sm_lows / sm_highs) * 100

Expand Down
10 changes: 4 additions & 6 deletions pyti/exponential_moving_average.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import absolute_import
from pyti import catch_errors
from pyti.function_helper import fill_for_noncomputable_vals
from six.moves import range


def exponential_moving_average(data, period):
Expand All @@ -13,12 +15,8 @@ def exponential_moving_average(data, period):
where: w = 2 / (N + 1)
"""
catch_errors.check_for_period_error(data, period)
emas = map(
lambda idx:
exponential_moving_average_helper(
data[idx - period + 1:idx + 1], period),
range(period - 1, len(data))
)
emas = [exponential_moving_average_helper(
data[idx - period + 1:idx + 1], period) for idx in range(period - 1, len(data))]
emas = fill_for_noncomputable_vals(data, emas)
return emas

Expand Down
1 change: 1 addition & 0 deletions pyti/function_helper.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
import numpy as np


Expand Down
1 change: 1 addition & 0 deletions pyti/hull_moving_average.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.weighted_moving_average import (
Expand Down
10 changes: 4 additions & 6 deletions pyti/ichimoku_cloud.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.function_helper import fill_for_noncomputable_vals
from six.moves import range


def conversion_base_line_helper(data, period):
"""
The only real difference between TenkanSen and KijunSen is the period value
"""
catch_errors.check_for_period_error(data, period)
cblh = map(
lambda idx:
(np.max(data[idx+1-period:idx+1]) +
np.min(data[idx+1-period:idx+1])) / 2,
range(period-1, len(data))
)
cblh = [(np.max(data[idx+1-period:idx+1]) +
np.min(data[idx+1-period:idx+1])) / 2 for idx in range(period-1, len(data))]

cblh = fill_for_noncomputable_vals(data, cblh)
return cblh
Expand Down
1 change: 1 addition & 0 deletions pyti/keltner_bands.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
import numpy as np
from pyti import catch_errors
from pyti.simple_moving_average import (
Expand Down
12 changes: 5 additions & 7 deletions pyti/linear_weighted_moving_average.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import absolute_import
from pyti import catch_errors
from pyti.function_helper import fill_for_noncomputable_vals
from six.moves import range


def linear_weighted_moving_average(data, period):
Expand All @@ -11,13 +13,9 @@ def linear_weighted_moving_average(data, period):
"""
catch_errors.check_for_period_error(data, period)

idx_period = range(1, period+1)
lwma = map(
lambda idx:
(sum([i * idx_period[data[idx-(period-1):idx+1].index(i)]
idx_period = list(range(1, period+1))
lwma = [(sum([i * idx_period[data[idx-(period-1):idx+1].index(i)]
for i in data[idx-(period-1):idx+1]])) /
sum(range(1, len(data[idx+1-period:idx+1])+1)),
range(period-1, len(data))
)
sum(range(1, len(data[idx+1-period:idx+1])+1)) for idx in range(period-1, len(data))]
lwma = fill_for_noncomputable_vals(data, lwma)
return lwma
Loading

0 comments on commit ffe741a

Please sign in to comment.