1
1
from Trading .model .history import History
2
2
from abc import ABC , abstractmethod
3
- from typing import Dict , List
3
+ from typing import Dict , List , Optional
4
+ from pydantic import BaseModel , ConfigDict
4
5
5
- class ScoreCalculator (ABC ):
6
+ class ScoreCalculator (BaseModel ):
6
7
'''
7
8
ScoreCalculator class is used to quantify a set of traits that is desirable
8
9
in stocks, based on their historical data. It takes a history object and a window size
@@ -14,39 +15,14 @@ class ScoreCalculator(ABC):
14
15
The ScoreCalculator class is used in the PerfectRange class to rank
15
16
stocks ranging behavior based on their historical data.
16
17
'''
17
- def __init__ ( self , window : int , is_bigger_better = False ) -> None :
18
- self . _window = window
19
- self . _is_bigger_better = is_bigger_better
18
+ window : int
19
+ is_bigger_better : bool = False
20
+
20
21
21
22
@abstractmethod
22
23
def calculate (self , history : History ) -> float :
23
24
pass
24
25
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
- def scores (self ):
49
- return self ._scores
50
26
51
27
class RangeScorer (ScoreCalculator ):
52
28
'''
@@ -58,9 +34,8 @@ class RangeScorer(ScoreCalculator):
58
34
below which x % of the lows are. It then calculates the ratio of these two price
59
35
levels and returns the ratio as the score.
60
36
'''
61
- def __init__ (self , window : int , x_percent : float = 10 ) -> None :
62
- super ().__init__ (window , is_bigger_better = True )
63
- self ._x_percent = x_percent
37
+ x_percent : float = 10.0
38
+ is_bigger_better : bool = False
64
39
65
40
def calculate (self , history : History ):
66
41
# order the highs and lows of the last periods
@@ -69,8 +44,8 @@ def calculate(self, history: History):
69
44
70
45
# get top lowest x% highs and top x% highest lows
71
46
length = len (ordered_highs )
72
- top_highs = ordered_highs [int (length / self ._x_percent )]
73
- top_lows = ordered_lows [- int (length / self ._x_percent )]
47
+ top_highs = ordered_highs [int (length / self .x_percent )]
48
+ top_lows = ordered_lows [- int (length / self .x_percent )]
74
49
75
50
# this represents the diminished range height
76
51
ratio = top_highs / top_lows
@@ -87,3 +62,28 @@ def calculate(self, history: History):
87
62
lows_std = lows_std / lows_mean
88
63
89
64
return ratio / (highs_std + lows_std )
65
+
66
+
67
+ class Ordering (BaseModel ):
68
+ '''
69
+ Ordering class is used to keep track of the ordering of stocks
70
+ based on their historical data. It takes a list of stocks and
71
+ orders them based on their historical data.
72
+ '''
73
+ top_n : int
74
+ score_calculator : RangeScorer
75
+ scores : Optional [Dict [str , float ]] = dict ()
76
+
77
+ model_config = ConfigDict (arbitrary_types_allowed = True )
78
+
79
+ def add_history (self , history : History ):
80
+ score = self .score_calculator .calculate (history )
81
+ score = round (score , 2 )
82
+ self .scores [history .symbol ] = score
83
+
84
+ is_bigger_better = self .score_calculator .is_bigger_better
85
+ if is_bigger_better :
86
+ self .scores = dict (sorted (self .scores .items (), key = lambda item : item [1 ],
87
+ reverse = True )[:self .top_n ])
88
+ else :
89
+ self .scores = dict (sorted (self .scores .items (), key = lambda item : item [1 ])[:self .top_n ])
0 commit comments