Skip to content

Commit 240aaca

Browse files
authored
Fix pydantic issue (#29)
* Fix pydantic issue and update variable names to more meaningful names in models.py * Update README.md
1 parent 3e6e201 commit 240aaca

File tree

4 files changed

+27
-31
lines changed

4 files changed

+27
-31
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ The description of the input data follows:
6363
- Maximum value of the stock in the stock price domain.
6464

6565
- `strategy` : list
66-
- A list of `Strategy`.
66+
- A list of strategy legs.
6767

6868
- `dividend_yield` : float, optional
6969
- Annualized dividend yield. Default is 0.0.
@@ -115,10 +115,10 @@ The description of the input data follows:
115115

116116
---
117117

118-
The `strategy` attribute can be either of type `OptionStrategy`, `StockStrategy`, or
119-
`ClosedPosition`.
118+
The `strategy` attribute is a list of strategy legs, where each leg can be of type
119+
`Option`, `Stock`, or `ClosedPosition`.
120120

121-
The `OptionStrategy` structure:
121+
The `Option` structure:
122122

123123
---
124124

@@ -149,7 +149,7 @@ The `OptionStrategy` structure:
149149

150150
---
151151

152-
`StockStrategy`:
152+
`Stock`:
153153

154154
---
155155

optionlab/__init__.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import typing
22

33

4-
VERSION = "1.3.0"
4+
VERSION = "1.3.1"
55

66

77
if typing.TYPE_CHECKING:
@@ -11,16 +11,16 @@
1111
Inputs,
1212
OptionType,
1313
OptionInfo,
14-
OptionStrategy,
14+
Option,
1515
Outputs,
1616
ClosedPosition,
1717
ProbabilityOfProfitArrayInputs,
1818
ProbabilityOfProfitInputs,
1919
BlackScholesInfo,
2020
Distribution,
21-
Strategy,
21+
StrategyLeg,
2222
StrategyType,
23-
StockStrategy,
23+
Stock,
2424
Country,
2525
Action,
2626
)
@@ -53,16 +53,16 @@
5353
"Inputs",
5454
"OptionType",
5555
"OptionInfo",
56-
"OptionStrategy",
56+
"Option",
5757
"Outputs",
5858
"ClosedPosition",
5959
"ProbabilityOfProfitArrayInputs",
6060
"ProbabilityOfProfitInputs",
6161
"BlackScholesInfo",
6262
"Distribution",
63-
"Strategy",
63+
"StrategyLeg",
6464
"StrategyType",
65-
"StockStrategy",
65+
"Stock",
6666
"Country",
6767
"Action",
6868
# engine
@@ -96,15 +96,15 @@
9696
"Outputs": (__package__, ".models"),
9797
"OptionType": (__package__, ".models"),
9898
"OptionInfo": (__package__, ".models"),
99-
"OptionStrategy": (__package__, ".models"),
99+
"Option": (__package__, ".models"),
100100
"ClosedPosition": (__package__, ".models"),
101101
"ProbabilityOfProfitArrayInputs": (__package__, ".models"),
102102
"ProbabilityOfProfitInputs": (__package__, ".models"),
103103
"BlackScholesInfo": (__package__, ".models"),
104104
"Distribution": (__package__, ".models"),
105-
"Strategy": (__package__, ".models"),
105+
"StrategyLeg": (__package__, ".models"),
106106
"StrategyType": (__package__, ".models"),
107-
"StockStrategy": (__package__, ".models"),
107+
"Stock": (__package__, ".models"),
108108
"Country": (__package__, ".models"),
109109
"Action": (__package__, ".models"),
110110
# engine

optionlab/engine.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
from optionlab.models import (
1313
Inputs,
1414
Action,
15-
OptionStrategy,
16-
StockStrategy,
15+
Option,
16+
Stock,
1717
ClosedPosition,
1818
Outputs,
1919
ProbabilityOfProfitInputs,
@@ -75,7 +75,7 @@ def _init_inputs(inputs: Inputs) -> EngineData:
7575
for i, strategy in enumerate(inputs.strategy):
7676
data.type.append(strategy.type)
7777

78-
if isinstance(strategy, OptionStrategy):
78+
if isinstance(strategy, Option):
7979
data.strike.append(strategy.strike)
8080
data.premium.append(strategy.premium)
8181
data.n.append(strategy.n)
@@ -110,7 +110,7 @@ def _init_inputs(inputs: Inputs) -> EngineData:
110110
else:
111111
raise ValueError("Expiration must be a date, an int or None.")
112112

113-
elif isinstance(strategy, StockStrategy):
113+
elif isinstance(strategy, Stock):
114114
data.n.append(strategy.n)
115115
data.action.append(strategy.action)
116116
data._previous_position.append(strategy.prev_pos or 0.0)

optionlab/models.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@
2727
]
2828

2929

30-
class BaseStrategy(BaseModel):
30+
class BaseLeg(BaseModel):
31+
n: int = Field(gt=0)
3132
action: Action
3233
prev_pos: float | None = None
3334

3435

35-
class StockStrategy(BaseStrategy):
36+
class Stock(BaseLeg):
3637
"""
3738
"type" : string
3839
It must be 'stock'. It is mandatory.
@@ -48,15 +49,12 @@ class StockStrategy(BaseStrategy):
4849
negative, it means that the position is closed and the
4950
difference between this price and the current price is
5051
considered in the payoff calculation.
51-
5252
"""
5353

5454
type: Literal["stock"] = "stock"
55-
n: int = Field(gt=0)
56-
premium: float | None = None
5755

5856

59-
class OptionStrategy(BaseStrategy):
57+
class Option(BaseLeg):
6058
"""
6159
"type" : string
6260
Either 'call' or 'put'. It is mandatory.
@@ -83,7 +81,6 @@ class OptionStrategy(BaseStrategy):
8381
type: OptionType
8482
strike: float = Field(gt=0)
8583
premium: float = Field(gt=0)
86-
n: int = Field(gt=0)
8784
expiration: dt.date | int | None = None
8885

8986
@field_validator("expiration")
@@ -107,7 +104,7 @@ class ClosedPosition(BaseModel):
107104
prev_pos: float
108105

109106

110-
Strategy = StockStrategy | OptionStrategy | ClosedPosition
107+
StrategyLeg = Stock | Option | ClosedPosition
111108

112109

113110
class ProbabilityOfProfitInputs(BaseModel):
@@ -203,7 +200,7 @@ class Inputs(BaseModel):
203200
interest_rate: float = Field(gt=0, le=0.2)
204201
min_stock: float
205202
max_stock: float
206-
strategy: list[Strategy] = Field(..., min_length=1, discriminator="type")
203+
strategy: list[StrategyLeg] = Field(..., min_length=1)
207204
dividend_yield: float = 0.0
208205
profit_target: float | None = None
209206
loss_limit: float | None = None
@@ -221,7 +218,7 @@ class Inputs(BaseModel):
221218

222219
@field_validator("strategy")
223220
@classmethod
224-
def validate_strategy(cls, v: list[Strategy]) -> list[Strategy]:
221+
def validate_strategy(cls, v: list[StrategyLeg]) -> list[StrategyLeg]:
225222
types = [strategy.type for strategy in v]
226223
if types.count("closed") > 1:
227224
raise ValueError("Only one position of type 'closed' is allowed!")
@@ -232,8 +229,7 @@ def validate_dates(self) -> "Inputs":
232229
expiration_dates = [
233230
strategy.expiration
234231
for strategy in self.strategy
235-
if isinstance(strategy, OptionStrategy)
236-
and isinstance(strategy.expiration, dt.date)
232+
if isinstance(strategy, Option) and isinstance(strategy.expiration, dt.date)
237233
]
238234
if self.start_date and self.target_date:
239235
if any(

0 commit comments

Comments
 (0)