Skip to content

Commit 4653193

Browse files
committed
Add ranker
1 parent 412a1ba commit 4653193

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

Trading/algo/ranker/__init__.py

Whitespace-only changes.

Trading/algo/ranker/ranker.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from Trading.model.history import History
2+
from abc import ABC, abstractmethod
3+
from typing import Dict, List
4+
5+
class ScoreCalculator(ABC):
6+
'''
7+
ScoreCalculator class is used to quantify a set of traits that is desirable
8+
in stocks, based on their historical data. It takes a history object and a window size
9+
and scores the stocks based on the historical data in the window.
10+
11+
This class can be used in order to determine which stocks are
12+
the best to trade based on their historical data.
13+
14+
The ScoreCalculator class is used in the PerfectRange class to rank
15+
stocks ranging behavior based on their historical data.
16+
'''
17+
def __init__(self, window: int, is_bigger_better=False) -> None:
18+
self._window = window
19+
self._is_bigger_better = is_bigger_better
20+
21+
@abstractmethod
22+
def calculate(self, history: History) -> float:
23+
pass
24+
25+
class Ordering:
26+
'''
27+
Ordering class is used to keep track of the ordering of stocks
28+
based on their historical data. It takes a list of stocks and
29+
orders them based on their historical data.
30+
'''
31+
def __init__(self, top_n: int, score_calculator: ScoreCalculator) -> None:
32+
self._top_n = top_n
33+
self._scores: Dict[str, float] = dict()
34+
self._score_calculator = score_calculator
35+
36+
def add_history(self, history: History):
37+
score = self._score_calculator.calculate(history)
38+
score = round(score, 2)
39+
self._scores[history.symbol] = score
40+
41+
is_bigger_better = self._score_calculator._is_bigger_better
42+
if is_bigger_better:
43+
self._scores = dict(sorted(self._scores.items(), key=lambda item: item[1],
44+
reverse=True)[:self._top_n])
45+
else:
46+
self._scores = dict(sorted(self._scores.items(), key=lambda item: item[1])[:self._top_n])
47+
48+
class RangeScorer(ScoreCalculator):
49+
'''
50+
RangeScorer class is used to score stocks based on their historical data.
51+
It takes a history object and a window size and scores the stocks based on
52+
their historical data in the window.
53+
54+
It finds the price level above which x % of the highs are and the price level
55+
below which x % of the lows are. It then calculates the ratio of these two price
56+
levels and returns the ratio as the score.
57+
'''
58+
def __init__(self, window: int, x_percent: float = 10) -> None:
59+
super().__init__(window, is_bigger_better=True)
60+
self._x_percent = x_percent
61+
62+
def calculate(self, history: History):
63+
# order the highs and lows of the last periods
64+
ordered_highs = sorted(history.high)
65+
ordered_lows = sorted(history.low)
66+
67+
# get top lowest x% highs and top x% highest lows
68+
length = len(ordered_highs)
69+
top_highs = ordered_highs[int(length/self._x_percent)]
70+
top_lows = ordered_lows[-int(length/self._x_percent)]
71+
72+
# this represents the diminished range height
73+
ratio = top_highs / top_lows
74+
75+
# minimize the standard deviation of highs and lows
76+
from Trading.utils.calculations import calculate_standard_deviation
77+
78+
highs_std = calculate_standard_deviation(ordered_highs)
79+
lows_std = calculate_standard_deviation(ordered_lows)
80+
81+
return ratio / (highs_std + lows_std)

0 commit comments

Comments
 (0)