Skip to content

Commit 5dead5c

Browse files
committed
Add latest version, upgraded and simplified
1 parent dfb92ea commit 5dead5c

File tree

2 files changed

+31
-32
lines changed

2 files changed

+31
-32
lines changed

Trading/algo/ranker/ranker.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
from Trading.model.history import History
1+
from Trading.model.history import History, OHLC
22
from abc import ABC, abstractmethod
33
from typing import Dict, List, Optional
44
from pydantic import BaseModel, ConfigDict
5+
from Trading.utils.custom_logging import get_logger
56

7+
LOGGER = get_logger(__file__)
68
class ScoreCalculator(BaseModel):
79
'''
810
ScoreCalculator class is used to quantify a set of traits that is desirable
@@ -16,8 +18,6 @@ class ScoreCalculator(BaseModel):
1618
stocks ranging behavior based on their historical data.
1719
'''
1820
window: int
19-
is_bigger_better: bool = False
20-
2121

2222
@abstractmethod
2323
def calculate(self, history: History) -> float:
@@ -35,33 +35,29 @@ class RangeScorer(ScoreCalculator):
3535
levels and returns the ratio as the score.
3636
'''
3737
x_percent: float = 10.0
38-
is_bigger_better: bool = False
3938

4039
def calculate(self, history: History):
41-
# order the highs and lows of the last periods
42-
ordered_highs = sorted(history.high)
43-
ordered_lows = sorted(history.low)
40+
# Calculate the number of top elements needed
41+
length = len(history.high)
42+
top_count = int(length / self.x_percent)
4443

45-
# get top lowest x% highs and top x% highest lows
46-
length = len(ordered_highs)
47-
top_highs = ordered_highs[int(length/self.x_percent)]
48-
top_lows = ordered_lows[-int(length/self.x_percent)]
44+
# Get the top lowest x% highs and top highest x% lows
45+
#top_highs = history.calculate_percentile(OHLC.HIGH, 100 - self.x_percent)
46+
#top_lows = history.calculate_percentile(OHLC.LOW, self.x_percent)
4947

50-
# this represents the diminished range height
51-
ratio = top_highs / top_lows
48+
# Calculate the diminished range height
49+
#ratio = top_highs / top_lows
5250

5351
# minimize the standard deviation of highs and lows
54-
from Trading.utils.calculations import calculate_standard_deviation, calculate_mean
55-
56-
highs_std = calculate_standard_deviation(ordered_highs)
57-
highs_mean = calculate_mean(ordered_highs)
58-
lows_std = calculate_standard_deviation(ordered_lows)
59-
lows_mean = calculate_mean(ordered_lows)
52+
highs_std = history.calculate_std(OHLC.HIGH)
53+
highs_mean = history.calculate_mean(OHLC.HIGH)
54+
lows_std = history.calculate_std(OHLC.LOW)
55+
lows_mean = history.calculate_mean(OHLC.LOW)
6056

6157
highs_std = highs_std / highs_mean
6258
lows_std = lows_std / lows_mean
6359

64-
return ratio / (highs_std + lows_std)
60+
return 1 / (highs_std + lows_std)
6561

6662

6763
class Ordering(BaseModel):
@@ -72,6 +68,7 @@ class Ordering(BaseModel):
7268
'''
7369
top_n: int
7470
score_calculator: RangeScorer
71+
is_bigger_better: bool = True
7572
scores: Optional[Dict[str, float]] = dict()
7673

7774
model_config = ConfigDict(arbitrary_types_allowed=True)
@@ -81,8 +78,7 @@ def add_history(self, history: History):
8178
score = round(score, 2)
8279
self.scores[history.symbol] = score
8380

84-
is_bigger_better = self.score_calculator.is_bigger_better
85-
if is_bigger_better:
81+
if self.is_bigger_better:
8682
self.scores = dict(sorted(self.scores.items(), key=lambda item: item[1],
8783
reverse=True)[:self.top_n])
8884
else:

Trading/utils/range/range.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
MAIN_LOGGER = get_logger("range.py")
66

7+
8+
79
def calculate_rank(history: History, periods: int):
810
# calculate how close to a perfect range the last periods are
911
# 0 means perfect range, 1 means no range
@@ -17,19 +19,21 @@ def calculate_rank(history: History, periods: int):
1719
sum_of_ranges += abs(h - l)
1820
return (range_size*periods - sum_of_ranges) / range_size
1921

22+
def calculate_rank_2(history: History, periods: int):
23+
# order the highs and lows of the last periods
24+
ordered_highs = sorted(history.high[-periods:])
25+
ordered_lows = sorted(history.low[-periods:])
26+
27+
# get top lowest 10% highs and top highest 10% lows
28+
top_highs = ordered_highs[int(periods/10)]
29+
top_lows = ordered_lows[-int(periods/10)]
2030

21-
def rank_histories(histories: List[History], periods: int, range_width: Optional[float] = None) -> Dict[str, float]:
22-
ranks = dict()
23-
for history in histories:
24-
rank = calculate_rank(history, periods)
25-
ranks[history.symbol] = rank
26-
ranks = dict(sorted(ranks.items(), key=lambda item: -item[1]))
27-
return ranks
31+
rank = -top_highs / top_lows
32+
return rank
2833

2934
class PerfectRange:
3035
def __init__(self, periods: int, top_n: int = 1, tolerance: Optional[float] = None):
3136
self.periods = periods
32-
self.histories: List[History] = []
3337
self.ranks: Dict[str, float] = dict()
3438
self.top_n = top_n
3539
self.tolerance = tolerance
@@ -49,8 +53,7 @@ def add_history(self, history: History, current_price: Optional[float], range_he
4953
return
5054
if range_height and max_h / min_l < range_height:
5155
return
52-
self.histories.append(history)
53-
rank = calculate_rank(history, self.periods)
56+
rank = calculate_rank_2(history, self.periods)
5457
rank = round(rank, 2)
5558
self.ranks[history.symbol] = rank
5659
self.ranks = dict(sorted(self.ranks.items(), key=lambda item: item[1])[:self.top_n])

0 commit comments

Comments
 (0)