quantmod 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quantmod/__init__.py +43 -0
- quantmod/_version.py +683 -0
- quantmod/datasets/__init__.py +24 -0
- quantmod/datasets/dataloader.py +61 -0
- quantmod/derivatives/__init__.py +23 -0
- quantmod/derivatives/options.py +47 -0
- quantmod/indicators/__init__.py +23 -0
- quantmod/indicators/indicators.py +51 -0
- quantmod/main.py +3 -0
- quantmod/markets/__init__.py +24 -0
- quantmod/markets/bb.py +48 -0
- quantmod/markets/yahoo.py +141 -0
- quantmod/models/__init__.py +28 -0
- quantmod/models/blackscholes.py +156 -0
- quantmod/models/montecarlo.py +115 -0
- quantmod/models/optioninputs.py +44 -0
- quantmod/risk/__init__.py +27 -0
- quantmod/risk/riskinputs.py +36 -0
- quantmod/risk/var.py +103 -0
- quantmod/risk/varbacktester.py +85 -0
- quantmod/timeseries/__init__.py +93 -0
- quantmod/timeseries/performance.py +237 -0
- quantmod/timeseries/timeseries.py +134 -0
- quantmod/utils.py +26 -0
- quantmod-0.0.1.dist-info/LICENSE.txt +203 -0
- quantmod-0.0.1.dist-info/METADATA +93 -0
- quantmod-0.0.1.dist-info/RECORD +30 -0
- quantmod-0.0.1.dist-info/WHEEL +5 -0
- quantmod-0.0.1.dist-info/entry_points.txt +2 -0
- quantmod-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
|
+
from typing import Optional,Tuple
|
|
4
|
+
from .optioninputs import OptionInputs
|
|
5
|
+
|
|
6
|
+
# Monte Carlo Option Pricing Engine
|
|
7
|
+
class MonteCarloOptionPricing:
|
|
8
|
+
"""
|
|
9
|
+
Class for Monte Carlo Option Pricing
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
inputs : OptionInputs
|
|
14
|
+
Option inputs parameters
|
|
15
|
+
initialspot : float, optional
|
|
16
|
+
Initial stock price
|
|
17
|
+
nsims : int, optional
|
|
18
|
+
Number of simulations
|
|
19
|
+
timestep : int, optional
|
|
20
|
+
Timestep, by default 252
|
|
21
|
+
barrier : float, optional
|
|
22
|
+
Barrier, by default None
|
|
23
|
+
rebate : int, optional
|
|
24
|
+
Rebate, by default None
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
attributes: float
|
|
29
|
+
call_vanilla, put_vanilla
|
|
30
|
+
|
|
31
|
+
call_asian, put_asian
|
|
32
|
+
|
|
33
|
+
upandoutcall
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self,
|
|
37
|
+
inputs: OptionInputs,
|
|
38
|
+
initialspot: float = Field(..., gt=0, description="Initial stock price"),
|
|
39
|
+
nsims: int = Field(..., gt=0, description="Number of simulations"),
|
|
40
|
+
timestep: int = 252,
|
|
41
|
+
barrier: Optional[float] = None,
|
|
42
|
+
rebate: Optional[int] = None
|
|
43
|
+
) -> None:
|
|
44
|
+
|
|
45
|
+
self.inputs = inputs
|
|
46
|
+
self.initialspot = initialspot
|
|
47
|
+
self.nsims = nsims
|
|
48
|
+
self.timestep = timestep
|
|
49
|
+
self.barrier = barrier
|
|
50
|
+
self.rebate = rebate
|
|
51
|
+
|
|
52
|
+
self.call_vanilla, self.put_vanilla = self._vanillaoption()
|
|
53
|
+
self.call_asian, self.put_asian = self._asianoption()
|
|
54
|
+
self.upandoutcall = self._upandoutcall()
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def _discount_factor(self) -> float:
|
|
58
|
+
return np.exp(-self.inputs.rate * self.inputs.ttm)
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def _pseudorandomnumber(self) -> np.ndarray:
|
|
62
|
+
return np.random.standard_normal(self.nsims)
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def _simulatepath(self) -> np.ndarray:
|
|
66
|
+
"""Simulate price path"""
|
|
67
|
+
np.random.seed(2024)
|
|
68
|
+
|
|
69
|
+
dt = self.inputs.ttm / self.timestep
|
|
70
|
+
|
|
71
|
+
S = np.zeros((self.timestep, self.nsims))
|
|
72
|
+
S[0] = self.initialspot
|
|
73
|
+
|
|
74
|
+
for i in range(0, self.timestep-1):
|
|
75
|
+
w = self._pseudorandomnumber
|
|
76
|
+
S[i+1] = S[i] * (1 + self.inputs.rate*dt + self.inputs.volatility*np.sqrt(dt)*w)
|
|
77
|
+
|
|
78
|
+
return S
|
|
79
|
+
|
|
80
|
+
def _vanillaoption(self) -> Tuple[float, float]:
|
|
81
|
+
"""Calculate vanilla option payoff"""
|
|
82
|
+
S = self._simulatepath
|
|
83
|
+
|
|
84
|
+
vanilla_call = self._discount_factor * np.mean(np.maximum(0, S[-1] - self.inputs.strike))
|
|
85
|
+
vanilla_put = self._discount_factor * np.mean(np.maximum(0, self.inputs.strike - S[-1]))
|
|
86
|
+
|
|
87
|
+
return [vanilla_call, vanilla_put]
|
|
88
|
+
|
|
89
|
+
def _asianoption(self) -> Tuple[float]:
|
|
90
|
+
"""Calculate asian option payoff"""
|
|
91
|
+
S = self._simulatepath
|
|
92
|
+
|
|
93
|
+
A = S.mean(axis=0)
|
|
94
|
+
|
|
95
|
+
asian_call = self._discount_factor * np.mean(np.maximum(0, A - self.inputs.strike))
|
|
96
|
+
asian_put = self._discount_factor * np.mean(np.maximum(0, self.inputs.strike - A))
|
|
97
|
+
|
|
98
|
+
return [asian_call, asian_put]
|
|
99
|
+
|
|
100
|
+
def _upandoutcall(self) -> float:
|
|
101
|
+
"""Calculate up-and-out barrier call option payoff"""
|
|
102
|
+
S = self._simulatepath
|
|
103
|
+
|
|
104
|
+
# Barrier shift
|
|
105
|
+
barriershift = self.barrier * np.exp(0.5826 * self.inputs.volatility * np.sqrt(self.inputs.ttm/self.timestep))
|
|
106
|
+
|
|
107
|
+
value = 0
|
|
108
|
+
for i in range(self.nsims):
|
|
109
|
+
if S[:,i].max () < barriershift:
|
|
110
|
+
value += np.maximum(0, S[-1,i] - self.inputs.strike)
|
|
111
|
+
else:
|
|
112
|
+
value += self.rebate
|
|
113
|
+
|
|
114
|
+
return self._discount_factor * value / self.nsims
|
|
115
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
class OptionInputs(BaseModel):
|
|
5
|
+
"""
|
|
6
|
+
Option inputs parameters
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
spot : float
|
|
11
|
+
Spot price of the underlying asset
|
|
12
|
+
strike : float
|
|
13
|
+
Strike price of the option
|
|
14
|
+
rate : float
|
|
15
|
+
Risk-free interest rate
|
|
16
|
+
ttm : float
|
|
17
|
+
Time to maturity in years
|
|
18
|
+
volatility : float
|
|
19
|
+
Volatility of the underlying asset
|
|
20
|
+
callprice : float | None
|
|
21
|
+
Default is None
|
|
22
|
+
Market price of the call option
|
|
23
|
+
putprice : float | None
|
|
24
|
+
Default is None
|
|
25
|
+
Market price of the put option
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
OptionInputs
|
|
30
|
+
Option inputs parameters
|
|
31
|
+
|
|
32
|
+
Raises
|
|
33
|
+
------
|
|
34
|
+
ValueError
|
|
35
|
+
If any of the input parameters are invalid
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
spot: float = Field(..., gt=0, description="Spot price of the underlying asset")
|
|
39
|
+
strike: float = Field(..., gt=0, description="Strike price of the option")
|
|
40
|
+
rate: float = Field(..., gt=0, le=1, description="Risk-free interest rate")
|
|
41
|
+
ttm: float = Field(..., gt=0, description="Time to maturity in years")
|
|
42
|
+
volatility: float = Field(..., gt=0, description="Volatility of the underlying asset")
|
|
43
|
+
callprice: Optional[float] = Field(default=None, ge=0, description="Market price of the call option")
|
|
44
|
+
putprice: Optional[float] = Field(default=None, ge=0, description="Market price of the put option")
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Quantmod Python Package
|
|
2
|
+
# https://kannansingaravelu.com/
|
|
3
|
+
|
|
4
|
+
# Copyright 2024 Kannan Singaravelu
|
|
5
|
+
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
|
|
18
|
+
from .riskinputs import RiskInputs
|
|
19
|
+
from .var import ValueAtRisk, ConditionalVaR
|
|
20
|
+
from .varbacktester import VarBacktester
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"RiskInputs",
|
|
24
|
+
"ValueAtRisk",
|
|
25
|
+
"ConditionalVaR",
|
|
26
|
+
"VarBacktester",
|
|
27
|
+
]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field, field_validator
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
class RiskInputs(BaseModel):
|
|
5
|
+
"""
|
|
6
|
+
RiskInputs parameters
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
returns : List[float]
|
|
11
|
+
List of historical returns
|
|
12
|
+
confidence_level : float
|
|
13
|
+
The confidence level for the VaR calculation
|
|
14
|
+
|
|
15
|
+
Returns
|
|
16
|
+
-------
|
|
17
|
+
RiskInputs
|
|
18
|
+
RiskInputs parameters
|
|
19
|
+
|
|
20
|
+
Raises
|
|
21
|
+
------
|
|
22
|
+
ValueError
|
|
23
|
+
If any of the input parameters are invalid
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
returns: List[float] = Field(..., description="List of historical returns")
|
|
27
|
+
confidence_level: float = Field(..., ge=0.0, le=1.0, description="The confidence level for the VaR calculation")
|
|
28
|
+
|
|
29
|
+
class Config:
|
|
30
|
+
arbitrary_types_allowed = True
|
|
31
|
+
|
|
32
|
+
@field_validator('returns')
|
|
33
|
+
def check_returns(cls, v):
|
|
34
|
+
if len(v) <= 252: # Assuming at least one year of daily data
|
|
35
|
+
raise ValueError("At least 252 returns are required for meaningful backtest")
|
|
36
|
+
return v
|
quantmod/risk/var.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import numpy as np
|
|
3
|
+
from scipy import stats
|
|
4
|
+
from arch import arch_model
|
|
5
|
+
from .riskinputs import RiskInputs
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ValueAtRisk:
|
|
10
|
+
"""
|
|
11
|
+
Class to calculate Value at Risk (VaR) based on returns and confidence level
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
inputs : RiskInputs
|
|
16
|
+
An instance of Risk inputs containing returns and confidence level
|
|
17
|
+
method : Literal['historical', 'parametric', 'montecarlo']
|
|
18
|
+
The method to calculate VaR, by default 'historical'
|
|
19
|
+
|
|
20
|
+
Returns
|
|
21
|
+
-------
|
|
22
|
+
attributes: float
|
|
23
|
+
var
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, inputs: RiskInputs, method: Literal['historical', 'parametric', 'montecarlo']) -> float:
|
|
27
|
+
self.inputs = inputs
|
|
28
|
+
self.returns = pd.Series(inputs.returns)
|
|
29
|
+
self.method = method
|
|
30
|
+
self.mean = np.mean(self.returns)
|
|
31
|
+
self.std = np.std(self.returns)
|
|
32
|
+
self.var = self._var()
|
|
33
|
+
|
|
34
|
+
def _pvar(self) -> float:
|
|
35
|
+
"""
|
|
36
|
+
Calculate the Value at Risk (VaR) at the specified confidence level using variance - covariance approach
|
|
37
|
+
"""
|
|
38
|
+
# return (self.mean + stats.norm.ppf(1-self.inputs.confidence_level) * self.std)
|
|
39
|
+
return np.round(stats.norm.ppf(1-self.inputs.confidence_level, self.mean, self.std),4)
|
|
40
|
+
|
|
41
|
+
def _hvar(self) -> float:
|
|
42
|
+
"""
|
|
43
|
+
Calculate the Value at Risk (VaR) at the specified confidence level using historical returns
|
|
44
|
+
"""
|
|
45
|
+
return np.round(np.percentile(self.returns, (1 - self.inputs.confidence_level) * 100),4)
|
|
46
|
+
|
|
47
|
+
def _mcvar(self) -> float:
|
|
48
|
+
"""
|
|
49
|
+
Calculate the Value at Risk (VaR) at the specified confidence level using Monte Carlo simulation
|
|
50
|
+
"""
|
|
51
|
+
simulated_returns = stats.norm.rvs(loc=self.mean, scale=self.std, size=5000)
|
|
52
|
+
return np.round(np.percentile(simulated_returns, (1 - self.inputs.confidence_level) * 100),4)
|
|
53
|
+
|
|
54
|
+
# def _garchvar(self) -> float:
|
|
55
|
+
# """
|
|
56
|
+
# Calculate the Value at Risk (VaR) at the specified confidence level using GARCH model
|
|
57
|
+
# """
|
|
58
|
+
# model = arch_model(self.returns*1000, vol='GARCH', p=1, q=1, dist="gaussian")
|
|
59
|
+
# fitted_model = model.fit(disp="off")
|
|
60
|
+
# conditional_volatilities = fitted_model.conditional_volatility
|
|
61
|
+
# return (stats.norm.ppf(1-self.inputs.confidence_level) * conditional_volatilities.iloc[-1]) / 1000
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _var(self) -> float:
|
|
65
|
+
if self.method == 'parametric':
|
|
66
|
+
return self._pvar()
|
|
67
|
+
elif self.method == 'historical':
|
|
68
|
+
return self._hvar()
|
|
69
|
+
elif self.method == 'montecarlo':
|
|
70
|
+
return self._mcvar()
|
|
71
|
+
# elif self.method == 'garch':
|
|
72
|
+
# return self._garchvar()
|
|
73
|
+
else:
|
|
74
|
+
raise ValueError("Invalid method")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class ConditionalVaR:
|
|
78
|
+
"""
|
|
79
|
+
Class to calculate Conditional Value at Risk (CVaR) aka Expected Shortfall (ES) based on historical returns and confidence level
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
inputs : RiskInputs
|
|
84
|
+
An instance of Risk inputs containing returns and confidence level
|
|
85
|
+
|
|
86
|
+
Returns
|
|
87
|
+
-------
|
|
88
|
+
attributes: float
|
|
89
|
+
CVaR
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
def __init__(self, inputs: RiskInputs) -> float:
|
|
93
|
+
self.inputs = inputs
|
|
94
|
+
self.returns = pd.Series(inputs.returns)
|
|
95
|
+
self.cvar = self._cvar()
|
|
96
|
+
|
|
97
|
+
def _cvar(self) -> float:
|
|
98
|
+
"""
|
|
99
|
+
Calculate the Conditional Value at Risk (CVaR) at the specified confidence level
|
|
100
|
+
"""
|
|
101
|
+
var = np.percentile(self.returns, (1 - self.inputs.confidence_level) * 100)
|
|
102
|
+
tail_returns = self.returns[self.returns <= var]
|
|
103
|
+
return np.round(tail_returns.mean() if len(tail_returns) > 0 else float('nan'),4)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import numpy as np
|
|
3
|
+
from scipy import stats
|
|
4
|
+
from tabulate import tabulate
|
|
5
|
+
from .riskinputs import RiskInputs
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class VarBacktester:
|
|
9
|
+
"""
|
|
10
|
+
Class to perform a backtest for Value at Risk (VaR) calculations with non-overlapping windows
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
inputs : RiskInputs
|
|
15
|
+
An instance of Risk inputs containing returns and confidence level
|
|
16
|
+
window_volatility : int, optional
|
|
17
|
+
The window size for the rolling volatility calculation, by default 21
|
|
18
|
+
window_forward : int, optional
|
|
19
|
+
The window size for the rolling forward calculation, by default 10
|
|
20
|
+
|
|
21
|
+
Returns
|
|
22
|
+
-------
|
|
23
|
+
attributes: tabular output
|
|
24
|
+
run
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, inputs: RiskInputs, window_volatility:int = 21, window_forward: int = 10) -> pd.DataFrame:
|
|
28
|
+
self.inputs = inputs
|
|
29
|
+
self.returns = pd.Series(inputs.returns)
|
|
30
|
+
self.window_volatility = window_volatility
|
|
31
|
+
self.window_forward = window_forward
|
|
32
|
+
self.run = self._runbacktest()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _runbacktest(self) -> str:
|
|
36
|
+
"""
|
|
37
|
+
Perform VaR backtest with non-overlapping windows
|
|
38
|
+
|
|
39
|
+
Returns
|
|
40
|
+
-------
|
|
41
|
+
str
|
|
42
|
+
A tabular output containing the results of the backtest
|
|
43
|
+
"""
|
|
44
|
+
# Create a dataframe with returns
|
|
45
|
+
data = pd.DataFrame({'returns': self.returns})
|
|
46
|
+
|
|
47
|
+
# Calculate rolling VaR
|
|
48
|
+
data['VaR'] = data['returns'].rolling(self.window_volatility).std()*np.sqrt(self.window_forward)*stats.norm.ppf(1-self.inputs.confidence_level)
|
|
49
|
+
|
|
50
|
+
# Calculate forward returns
|
|
51
|
+
data['shifted_returns'] = data['returns'].shift(-2) # non overlapping window
|
|
52
|
+
data['forward_returns'] = data['shifted_returns'].rolling(window=self.window_forward).sum()
|
|
53
|
+
data['shifted_forward_returns'] = data['forward_returns'].shift(-self.window_forward+1)
|
|
54
|
+
|
|
55
|
+
# Identify breaches
|
|
56
|
+
data['breach'] = data['shifted_forward_returns'] < data['VaR']
|
|
57
|
+
|
|
58
|
+
# Calculate number and percentage of breaches
|
|
59
|
+
total_breaches = data['breach'].sum()
|
|
60
|
+
total_observations = len(data) - self.window_volatility - self.window_forward
|
|
61
|
+
percentage_breaches = (total_breaches / total_observations) * 100 if total_observations > 0 else np.nan
|
|
62
|
+
|
|
63
|
+
# Calculate continuous breaches
|
|
64
|
+
data['breach_shift'] = data['breach'].shift(1)
|
|
65
|
+
data['continuous_breaches'] = (data['breach'] & (data['breach'] == data['breach_shift'])).astype(int)
|
|
66
|
+
number_continuous_breaches = data['continuous_breaches'].sum()
|
|
67
|
+
|
|
68
|
+
# # Print data of breaches
|
|
69
|
+
# print(data[data['breach']])
|
|
70
|
+
|
|
71
|
+
# Conditional probability of breaches
|
|
72
|
+
non_nan_breaches = data['breach'].dropna()
|
|
73
|
+
conditional_probability = non_nan_breaches.mean() if len(non_nan_breaches) > 0 else np.nan
|
|
74
|
+
|
|
75
|
+
# Ouput results in tabular format
|
|
76
|
+
header = ['Backtest Results', 'Values']
|
|
77
|
+
table = [
|
|
78
|
+
['Actual Breaches', total_breaches],
|
|
79
|
+
['Percentage of Actual Breaches', percentage_breaches],
|
|
80
|
+
['Expected Breaches', int(total_observations*(1-self.inputs.confidence_level))],
|
|
81
|
+
['Percentage of Expected Breaches', (1-self.inputs.confidence_level)*100],
|
|
82
|
+
['Number of Continuous Breaches', number_continuous_breaches],
|
|
83
|
+
['Conditional Probability of Breaches', conditional_probability*100]]
|
|
84
|
+
|
|
85
|
+
return tabulate(table,headers=header, floatfmt=(".2f"))
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Quantmod Python Package
|
|
2
|
+
# https://kannansingaravelu.com/
|
|
3
|
+
|
|
4
|
+
# Copyright 2024 Kannan Singaravelu
|
|
5
|
+
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
from .timeseries import (
|
|
21
|
+
seriesHi,
|
|
22
|
+
seriesLo,
|
|
23
|
+
Op,
|
|
24
|
+
Hi,
|
|
25
|
+
Lo,
|
|
26
|
+
Cl,
|
|
27
|
+
Vo,
|
|
28
|
+
Ad,
|
|
29
|
+
OpCl,
|
|
30
|
+
OpHi,
|
|
31
|
+
OpLo,
|
|
32
|
+
HiCl,
|
|
33
|
+
HiLo,
|
|
34
|
+
LoCl,
|
|
35
|
+
Gap,
|
|
36
|
+
lag,
|
|
37
|
+
lead,
|
|
38
|
+
last,
|
|
39
|
+
first,
|
|
40
|
+
trend_score,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
from .performance import (
|
|
45
|
+
periodReturn,
|
|
46
|
+
dailyReturn,
|
|
47
|
+
weeklyReturn,
|
|
48
|
+
monthlyReturn,
|
|
49
|
+
quarterlyReturn,
|
|
50
|
+
annualReturn,
|
|
51
|
+
allReturn,
|
|
52
|
+
cagr,
|
|
53
|
+
volatility,
|
|
54
|
+
sharpe,
|
|
55
|
+
maxdd,
|
|
56
|
+
calmar
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
"seriesHi",
|
|
62
|
+
"seriesLo",
|
|
63
|
+
"Op",
|
|
64
|
+
"Hi",
|
|
65
|
+
"Lo",
|
|
66
|
+
"Cl",
|
|
67
|
+
"Vo",
|
|
68
|
+
"Ad",
|
|
69
|
+
"OpCl",
|
|
70
|
+
"OpHi",
|
|
71
|
+
"OpLo",
|
|
72
|
+
"HiCl",
|
|
73
|
+
"HiLo",
|
|
74
|
+
"LoCl",
|
|
75
|
+
"Gap",
|
|
76
|
+
"lag",
|
|
77
|
+
"lead",
|
|
78
|
+
"last",
|
|
79
|
+
"first",
|
|
80
|
+
"trend_score",
|
|
81
|
+
"periodReturn",
|
|
82
|
+
"dailyReturn",
|
|
83
|
+
"weeklyReturn",
|
|
84
|
+
"monthlyReturn",
|
|
85
|
+
"quarterlyReturn",
|
|
86
|
+
"annualReturn",
|
|
87
|
+
"allReturn",
|
|
88
|
+
"cagr",
|
|
89
|
+
"volatility",
|
|
90
|
+
"sharpe",
|
|
91
|
+
"maxdd",
|
|
92
|
+
"calmar",
|
|
93
|
+
]
|