RiskLabAI 0.0.74__tar.gz → 0.0.78__tar.gz
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.
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/PKG-INFO +4 -1
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/validation/purged_kfold.py +28 -21
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/pde/equation.py +104 -10
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/pde/model.py +157 -35
- risklabai-0.0.78/RiskLabAI/pde/solver.py +401 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI.egg-info/PKG-INFO +4 -1
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI.egg-info/SOURCES.txt +1 -0
- risklabai-0.0.78/RiskLabAI.egg-info/requires.txt +3 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/setup.cfg +5 -1
- RiskLabAI-0.0.74/RiskLabAI/pde/solver.py +0 -173
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/LICENSE +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/README.md +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/backtest_statistics.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/backtest_synthetic_data.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/backtset_overfitting_in_the_machine_learning_era_simulation.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/bet_sizing.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/probabilistic_sharpe_ratio.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/probability_of_backtest_overfitting.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/strategy_risk.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/test_set_overfitting.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/validation/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/validation/combinatorial_purged.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/validation/cross_validator_controller.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/validation/cross_validator_factory.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/validation/cross_validator_interface.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/validation/kfold.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/backtest/validation/walk_forward.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/cluster/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/cluster/clustering.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/controller/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/controller/bars_initializer.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/controller/data_structure_controller.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/denoise/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/denoise/denoising.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/differentiation/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/differentiation/differentiation.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/distance/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/distance/distance_metric.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/labeling/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/labeling/financial_labels.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/labeling/labeling.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/abstract_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/abstract_imbalance_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/abstract_information_driven_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/abstract_run_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/data_structures_lopez.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/filtering_lopez.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/hedging.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/imbalance_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/infomation_driven_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/run_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/standard_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/standard_bars_lopez.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/time_bars.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/structures/utilities_lopez.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/synthetic_data/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/synthetic_data/drift_burst_hypothesis.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/synthetic_data/synthetic_controlled_environment.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/weights/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/data/weights/sample_weights.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/ensemble/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/ensemble/bagging_classifier_accuracy.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/entropy_features/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/entropy_features/entropy.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/entropy_features/kontoyiannis.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/entropy_features/lempel_ziv.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/entropy_features/plug_in.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/entropy_features/pmf.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/entropy_features/shannon.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/clustered_feature_importance_mda.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/clustered_feature_importance_mdi.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/clustering.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/feature_importance_controller.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/feature_importance_factory.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/feature_importance_mda.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/feature_importance_mdi.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/feature_importance_sfi.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/feature_importance_strategy.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/generate_synthetic_data.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/orthogonal_features.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/feature_importance/weighted_tau.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/microstructural_features/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/microstructural_features/bekker_parkinson_volatility_estimator.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/microstructural_features/corwin_schultz.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/structural_breaks/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/features/structural_breaks/structural_breaks.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/hpc/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/hpc/hpc.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/modeling/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/modeling/optimization/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/modeling/optimization/hrp.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/modeling/optimization/hyper_parameter_tuning.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/modeling/optimization/nco.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/pde/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/utils/__init__.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/utils/constants.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/utils/ewma.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/utils/momentum_mean_reverting_strategy_sides.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/utils/progress.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI/utils/smoothing_average.py +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI.egg-info/dependency_links.txt +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI.egg-info/entry_points.txt +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/RiskLabAI.egg-info/top_level.txt +0 -0
- {RiskLabAI-0.0.74 → risklabai-0.0.78}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: RiskLabAI
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.78
|
|
4
4
|
Summary: Financial AI using Python.
|
|
5
5
|
Home-page: https://github.com/RiskLabAI/RiskLabAI.py
|
|
6
6
|
Author: RiskLab
|
|
@@ -12,3 +12,6 @@ Classifier: License :: OSI Approved :: BSD License
|
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
+
Requires-Dist: scipy
|
|
16
|
+
Requires-Dist: ta
|
|
17
|
+
Requires-Dist: quantecon
|
|
@@ -45,36 +45,43 @@ class PurgedKFold(CrossValidator):
|
|
|
45
45
|
|
|
46
46
|
indices_to_drop: Set[int] = set()
|
|
47
47
|
embargo_length = int(len(data_info_range) * embargo_fraction)
|
|
48
|
+
sorted_test_time_range = test_time_range.sort_index().copy()
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
if not continous_test_times:
|
|
51
|
+
sorted_test_time_range = pd.DataFrame({
|
|
52
|
+
'start' : sorted_test_time_range.index,
|
|
53
|
+
'end' : sorted_test_time_range.values
|
|
54
|
+
})
|
|
55
|
+
# Identify where the new range starts immediately after or before the previous range ends
|
|
56
|
+
gaps = sorted_test_time_range['start'] > sorted_test_time_range['end'].shift(1)
|
|
57
|
+
# Cumulative sum to identify contiguous blocks
|
|
58
|
+
blocks = gaps.cumsum()
|
|
59
|
+
# Aggregate to find the min start and max end for each block
|
|
60
|
+
effective_test_time_range = sorted_test_time_range.groupby(blocks).agg({'start': 'min', 'end': 'max'})
|
|
61
|
+
effective_test_time_range = pd.Series(effective_test_time_range['end'].values, index=effective_test_time_range['start'])
|
|
62
|
+
|
|
63
|
+
else:
|
|
64
|
+
effective_test_time_range = pd.Series(sorted_test_time_range.iloc[-1], index=[sorted_test_time_range.index[0]])
|
|
50
65
|
|
|
51
66
|
if embargo_length == 0:
|
|
52
|
-
embargoed_data_info_range = pd.Series(
|
|
67
|
+
embargoed_data_info_range = pd.Series(effective_test_time_range.values, index=effective_test_time_range.values)
|
|
53
68
|
|
|
54
69
|
else:
|
|
55
|
-
effective_sample = data_info_range.loc[
|
|
70
|
+
effective_sample = data_info_range.loc[effective_test_time_range.index.min():].copy().drop_duplicates()
|
|
56
71
|
embargoed_data_info_range = pd.Series(effective_sample.values, index=effective_sample.values)
|
|
57
|
-
embargoed_data_info_range = embargoed_data_info_range.shift(-embargo_length).fillna(embargoed_data_info_range.values[-1])
|
|
58
|
-
|
|
59
|
-
for start_ix, end_ix in effective_test_time_range.items():
|
|
60
|
-
# Adding the embargo period
|
|
61
|
-
end_ix_embargoed = embargoed_data_info_range.loc[end_ix]
|
|
62
|
-
|
|
63
|
-
overlapping_start = data_info_range[
|
|
64
|
-
(start_ix <= data_info_range.index) & (data_info_range.index <= end_ix_embargoed)
|
|
65
|
-
].index
|
|
72
|
+
embargoed_data_info_range = embargoed_data_info_range.shift(-embargo_length).fillna(embargoed_data_info_range.values[-1])
|
|
66
73
|
|
|
67
|
-
|
|
68
|
-
(start_ix <= data_info_range) & (data_info_range <= end_ix_embargoed)
|
|
69
|
-
].index
|
|
74
|
+
effective_ranges = pd.Series(embargoed_data_info_range.loc[effective_test_time_range].values, index=effective_test_time_range.index)
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
(data_info_range.index <= start_ix) & (end_ix_embargoed <= data_info_range)
|
|
73
|
-
].index
|
|
76
|
+
for start_ix, end_ix_embargoed in effective_ranges.items():
|
|
74
77
|
|
|
75
|
-
indices_to_drop.update(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
indices_to_drop.update(
|
|
79
|
+
data_info_range[
|
|
80
|
+
((start_ix <= data_info_range.index) & (data_info_range.index <= end_ix_embargoed)) |
|
|
81
|
+
((start_ix <= data_info_range) & (data_info_range <= end_ix_embargoed)) |
|
|
82
|
+
((data_info_range.index <= start_ix) & (end_ix_embargoed <= data_info_range))
|
|
83
|
+
].index
|
|
84
|
+
)
|
|
78
85
|
|
|
79
86
|
return data_info_range.drop(indices_to_drop)
|
|
80
87
|
|
|
@@ -89,8 +89,8 @@ class Equation:
|
|
|
89
89
|
Tensor: tensor of size [batch_size, 1] containing terminal values
|
|
90
90
|
"""
|
|
91
91
|
raise NotImplementedError
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
|
|
93
|
+
|
|
94
94
|
class PricingDefaultRisk(Equation):
|
|
95
95
|
"""
|
|
96
96
|
Args:
|
|
@@ -127,7 +127,7 @@ class PricingDefaultRisk(Equation):
|
|
|
127
127
|
x_sample[:, :, 0] = np.ones([num_sample, self.dim]) * self.x_init
|
|
128
128
|
for i in range(self.num_time_interval):
|
|
129
129
|
x_sample[:, :, i + 1] = (1 + self.mu_bar * self.delta_t) * x_sample[:, :, i] + (
|
|
130
|
-
self.
|
|
130
|
+
self.sigma_matrix(x_sample[:, :, i]) * dw_sample[:, :, i])
|
|
131
131
|
return dw_sample, x_sample
|
|
132
132
|
|
|
133
133
|
def r_u(self, t, x, y, z)-> torch.Tensor:
|
|
@@ -161,7 +161,10 @@ class PricingDefaultRisk(Equation):
|
|
|
161
161
|
torch.Tensor: tensor of size [batch_size, 1] containing H(z)
|
|
162
162
|
"""
|
|
163
163
|
return torch.zeros((x.size()[0],1))
|
|
164
|
-
|
|
164
|
+
|
|
165
|
+
def sigma_matrix(self,x):
|
|
166
|
+
return self.sigma * x
|
|
167
|
+
|
|
165
168
|
|
|
166
169
|
def terminal(self, t, x)-> torch.Tensor:
|
|
167
170
|
"""
|
|
@@ -187,7 +190,95 @@ class PricingDefaultRisk(Equation):
|
|
|
187
190
|
"""
|
|
188
191
|
return nn.ReLU()(torch.min(x, 2 , keepdim= True)[0])
|
|
189
192
|
|
|
190
|
-
|
|
193
|
+
|
|
194
|
+
class HJBLQ(Equation):
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
eqn_config (dict): dictionary containing PDE configuration parameters
|
|
199
|
+
"""
|
|
200
|
+
|
|
201
|
+
def __init__(self, eqn_config: dict):
|
|
202
|
+
super().__init__(eqn_config)
|
|
203
|
+
|
|
204
|
+
self.x_init = np.zeros(self.dim)
|
|
205
|
+
self.sigma = np.sqrt(2.0)
|
|
206
|
+
self.lambd = 1.0
|
|
207
|
+
|
|
208
|
+
def sample(self, num_sample: int) -> tuple:
|
|
209
|
+
"""
|
|
210
|
+
Sample forward SDE.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
num_sample (int): number of samples to generate
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
tuple: tuple of two tensors: dw_sample of size [num_sample, dim, num_time_interval] and
|
|
217
|
+
x_sample of size [num_sample, dim, num_time_interval+1]
|
|
218
|
+
"""
|
|
219
|
+
dw_sample = np.random.normal(size=[num_sample, self.dim, self.num_time_interval]) * self.sqrt_delta_t
|
|
220
|
+
x_sample = np.zeros([num_sample, self.dim, self.num_time_interval + 1])
|
|
221
|
+
x_sample[:, :, 0] = np.ones([num_sample, self.dim]) * self.x_init
|
|
222
|
+
for i in range(self.num_time_interval):
|
|
223
|
+
x_sample[:, :, i + 1] = x_sample[:, :, i] + self.sigma * dw_sample[:, :, i]
|
|
224
|
+
return dw_sample, x_sample
|
|
225
|
+
|
|
226
|
+
def r_u(self, t: float, x: torch.Tensor, y: torch.Tensor, z: torch.Tensor) -> torch.Tensor:
|
|
227
|
+
"""
|
|
228
|
+
Interest rate in the PDE.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
t (float): current time
|
|
232
|
+
x (torch.Tensor): tensor of size [batch_size, dim] containing space coordinates
|
|
233
|
+
y (torch.Tensor): tensor of size [batch_size, 1] containing function values
|
|
234
|
+
z (torch.Tensor): tensor of size [batch_size, dim] containing gradients
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
torch.Tensor: tensor of size [batch_size, 1] containing generator values
|
|
238
|
+
"""
|
|
239
|
+
return torch.ones((x.size()[0],)) * 0
|
|
240
|
+
|
|
241
|
+
def h_z(self, t: float, x: torch.Tensor,y: torch.Tensor, z: torch.Tensor) -> torch.Tensor:
|
|
242
|
+
"""
|
|
243
|
+
Function to compute <h,z> in the PDE.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
t (float): current time
|
|
247
|
+
x (torch.Tensor): tensor of size [batch_size, dim] containing space coordinates
|
|
248
|
+
y (torch.Tensor): tensor of size [batch_size, 1] containing function value
|
|
249
|
+
z (torch.Tensor): tensor of size [batch_size, dim] containing gradients
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
torch.Tensor: tensor of size [batch_size, 1] containing H(z)
|
|
253
|
+
"""
|
|
254
|
+
return torch.sum(torch.square(z), dim=1)/ (self.sigma**2)
|
|
255
|
+
|
|
256
|
+
def terminal(self, t: float, x: torch.Tensor) -> torch.Tensor:
|
|
257
|
+
"""
|
|
258
|
+
Terminal condition of the PDE.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
t (float): current time
|
|
262
|
+
x (torch.Tensor): tensor of size [batch_size, dim] containing space coordinates
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
torch.Tensor: tensor of size [batch_size, 1] containing terminal values
|
|
266
|
+
"""
|
|
267
|
+
return torch.log(0.5 * (1 + torch.norm(x, dim=1)**2))
|
|
268
|
+
def sigma_matrix(self,x):
|
|
269
|
+
return self.sigma
|
|
270
|
+
def terminal_for_sample(self, x)-> torch.Tensor:
|
|
271
|
+
"""
|
|
272
|
+
Terminal condition of the PDE.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
x (torch.Tensor): tensor of size [num_sample,batch_size, dim] containing space coordinates
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
torch.Tensor: tensor of size [num_sample ,batch_size, 1] containing terminal values
|
|
279
|
+
"""
|
|
280
|
+
return torch.sum(x ** 2, dim=2 ,keepdim=True )
|
|
281
|
+
|
|
191
282
|
class BlackScholesBarenblatt(Equation):
|
|
192
283
|
"""
|
|
193
284
|
|
|
@@ -218,7 +309,7 @@ class BlackScholesBarenblatt(Equation):
|
|
|
218
309
|
x_sample[:, :, 0] = np.ones((num_sample, self.dim)) * self.x_init
|
|
219
310
|
for i in range(self.num_time_interval):
|
|
220
311
|
x_sample[:, :, i + 1] = (1 + self.mu_bar * self.delta_t) * x_sample[:, :, i] + (
|
|
221
|
-
self.
|
|
312
|
+
self.sigma_matrix(x_sample[:, :, i]) * dw_sample[:, :, i])
|
|
222
313
|
return dw_sample, x_sample
|
|
223
314
|
|
|
224
315
|
def r_u(self, t: float, x: torch.Tensor, y: torch.Tensor, z: torch.Tensor) -> torch.Tensor:
|
|
@@ -263,7 +354,9 @@ class BlackScholesBarenblatt(Equation):
|
|
|
263
354
|
torch.Tensor: tensor of size [batch_size, 1] containing terminal values
|
|
264
355
|
"""
|
|
265
356
|
return torch.sum(x ** 2, dim=1)
|
|
266
|
-
def
|
|
357
|
+
def sigma_matrix(self,x):
|
|
358
|
+
return self.sigma * x
|
|
359
|
+
def terminal_for_sample(self, x)-> torch.Tensor:
|
|
267
360
|
"""
|
|
268
361
|
Terminal condition of the PDE.
|
|
269
362
|
|
|
@@ -274,6 +367,7 @@ def terminal_for_sample(self, x)-> torch.Tensor:
|
|
|
274
367
|
torch.Tensor: tensor of size [num_sample ,batch_size, 1] containing terminal values
|
|
275
368
|
"""
|
|
276
369
|
return torch.sum(x ** 2, dim=2 ,keepdim=True )
|
|
370
|
+
|
|
277
371
|
class PricingDiffRate(Equation):
|
|
278
372
|
"""
|
|
279
373
|
Nonlinear Black-Scholes equation with different interest rates for borrowing and lending
|
|
@@ -319,8 +413,9 @@ class PricingDiffRate(Equation):
|
|
|
319
413
|
|
|
320
414
|
def terminal(self, t, x):
|
|
321
415
|
temp = torch.max(x, 1)[0]
|
|
322
|
-
return
|
|
323
|
-
|
|
416
|
+
return nn.ReLU()(temp - 120) - 2*nn.ReLU()(temp - 150)
|
|
417
|
+
def sigma_matrix(self,x):
|
|
418
|
+
return self.sigma * x
|
|
324
419
|
def terminal_for_sample(self, x)-> torch.Tensor:
|
|
325
420
|
"""
|
|
326
421
|
Terminal condition of the PDE.
|
|
@@ -333,4 +428,3 @@ class PricingDiffRate(Equation):
|
|
|
333
428
|
"""
|
|
334
429
|
temp = torch.max(x, 2 , keep_dim = True)[0]
|
|
335
430
|
return torch.maximum(temp - 120, torch.tensor(0))
|
|
336
|
-
|
|
@@ -6,7 +6,7 @@ class TimeNet(Module):
|
|
|
6
6
|
Neural network model for time dimension
|
|
7
7
|
"""
|
|
8
8
|
def __init__(
|
|
9
|
-
self,
|
|
9
|
+
self,
|
|
10
10
|
output_dim: int
|
|
11
11
|
):
|
|
12
12
|
"""
|
|
@@ -27,9 +27,10 @@ class TimeNet(Module):
|
|
|
27
27
|
self.tanh3 = Tanh()
|
|
28
28
|
self.tanh4 = Tanh()
|
|
29
29
|
self.tanh5 = Tanh()
|
|
30
|
+
self.tanh6 = Tanh()
|
|
30
31
|
|
|
31
32
|
def forward(
|
|
32
|
-
self,
|
|
33
|
+
self,
|
|
33
34
|
x: torch.Tensor
|
|
34
35
|
) -> torch.Tensor:
|
|
35
36
|
"""
|
|
@@ -51,6 +52,7 @@ class TimeNet(Module):
|
|
|
51
52
|
x = self.layer5(x)
|
|
52
53
|
x = self.tanh5(x)
|
|
53
54
|
x = self.layer6(x)
|
|
55
|
+
x = self.tanh6(x)
|
|
54
56
|
return x
|
|
55
57
|
|
|
56
58
|
|
|
@@ -59,8 +61,8 @@ class Net1(Module):
|
|
|
59
61
|
A class for defining a neural network with a single linear layer.
|
|
60
62
|
"""
|
|
61
63
|
def __init__(
|
|
62
|
-
self,
|
|
63
|
-
input_dim: int,
|
|
64
|
+
self,
|
|
65
|
+
input_dim: int,
|
|
64
66
|
output_dim: int
|
|
65
67
|
):
|
|
66
68
|
"""
|
|
@@ -76,7 +78,7 @@ class Net1(Module):
|
|
|
76
78
|
self.bn = BatchNorm1d(output_dim)
|
|
77
79
|
|
|
78
80
|
def forward(
|
|
79
|
-
self,
|
|
81
|
+
self,
|
|
80
82
|
x: torch.Tensor
|
|
81
83
|
) -> torch.Tensor:
|
|
82
84
|
"""
|
|
@@ -99,11 +101,11 @@ For implementing Deep-Time-SetTransformer we have used code written by authors o
|
|
|
99
101
|
|
|
100
102
|
class MAB(nn.Module):
|
|
101
103
|
def __init__(
|
|
102
|
-
self,
|
|
103
|
-
dim_q: int,
|
|
104
|
-
dim_k: int,
|
|
105
|
-
dim_v: int,
|
|
106
|
-
num_heads: int,
|
|
104
|
+
self,
|
|
105
|
+
dim_q: int,
|
|
106
|
+
dim_k: int,
|
|
107
|
+
dim_v: int,
|
|
108
|
+
num_heads: int,
|
|
107
109
|
ln: bool = False
|
|
108
110
|
):
|
|
109
111
|
"""
|
|
@@ -127,8 +129,8 @@ class MAB(nn.Module):
|
|
|
127
129
|
self.fc_o = nn.Linear(dim_v, dim_v)
|
|
128
130
|
|
|
129
131
|
def forward(
|
|
130
|
-
self,
|
|
131
|
-
q: torch.Tensor,
|
|
132
|
+
self,
|
|
133
|
+
q: torch.Tensor,
|
|
132
134
|
k: torch.Tensor
|
|
133
135
|
) -> torch.Tensor:
|
|
134
136
|
"""
|
|
@@ -155,10 +157,10 @@ class MAB(nn.Module):
|
|
|
155
157
|
|
|
156
158
|
class SAB(nn.Module):
|
|
157
159
|
def __init__(
|
|
158
|
-
self,
|
|
159
|
-
dim_in: int,
|
|
160
|
-
dim_out: int,
|
|
161
|
-
num_heads: int,
|
|
160
|
+
self,
|
|
161
|
+
dim_in: int,
|
|
162
|
+
dim_out: int,
|
|
163
|
+
num_heads: int,
|
|
162
164
|
ln: bool = False
|
|
163
165
|
):
|
|
164
166
|
"""
|
|
@@ -173,7 +175,7 @@ class SAB(nn.Module):
|
|
|
173
175
|
self.mab = MAB(dim_in, dim_in, dim_out, num_heads, ln=ln)
|
|
174
176
|
|
|
175
177
|
def forward(
|
|
176
|
-
self,
|
|
178
|
+
self,
|
|
177
179
|
x: torch.Tensor
|
|
178
180
|
) -> torch.Tensor:
|
|
179
181
|
"""
|
|
@@ -186,11 +188,11 @@ class SAB(nn.Module):
|
|
|
186
188
|
|
|
187
189
|
class ISAB(nn.Module):
|
|
188
190
|
def __init__(
|
|
189
|
-
self,
|
|
190
|
-
dim_in: int,
|
|
191
|
-
dim_out: int,
|
|
192
|
-
num_heads: int,
|
|
193
|
-
num_inds: int,
|
|
191
|
+
self,
|
|
192
|
+
dim_in: int,
|
|
193
|
+
dim_out: int,
|
|
194
|
+
num_heads: int,
|
|
195
|
+
num_inds: int,
|
|
194
196
|
ln: bool = False
|
|
195
197
|
):
|
|
196
198
|
"""
|
|
@@ -209,7 +211,7 @@ class ISAB(nn.Module):
|
|
|
209
211
|
self.mab1 = MAB(dim_in, dim_out, dim_out, num_heads, ln=ln)
|
|
210
212
|
|
|
211
213
|
def forward(
|
|
212
|
-
self,
|
|
214
|
+
self,
|
|
213
215
|
x: torch.Tensor
|
|
214
216
|
) -> torch.Tensor:
|
|
215
217
|
"""
|
|
@@ -223,10 +225,10 @@ class ISAB(nn.Module):
|
|
|
223
225
|
|
|
224
226
|
class PMA(nn.Module):
|
|
225
227
|
def __init__(
|
|
226
|
-
self,
|
|
227
|
-
dim: int,
|
|
228
|
-
num_heads: int,
|
|
229
|
-
num_seeds: int,
|
|
228
|
+
self,
|
|
229
|
+
dim: int,
|
|
230
|
+
num_heads: int,
|
|
231
|
+
num_seeds: int,
|
|
230
232
|
ln: bool = False
|
|
231
233
|
):
|
|
232
234
|
"""
|
|
@@ -243,7 +245,7 @@ class PMA(nn.Module):
|
|
|
243
245
|
self.mab = MAB(dim, dim, dim, num_heads, ln=ln)
|
|
244
246
|
|
|
245
247
|
def forward(
|
|
246
|
-
self,
|
|
248
|
+
self,
|
|
247
249
|
x: torch.Tensor
|
|
248
250
|
) -> torch.Tensor:
|
|
249
251
|
"""
|
|
@@ -375,12 +377,128 @@ class DeepTimeSetTransformer(nn.Module):
|
|
|
375
377
|
output = self.time_layer4(t, output)
|
|
376
378
|
output = nn.ReLU()(output)
|
|
377
379
|
output = self.time_layer5(t, output)
|
|
378
|
-
|
|
380
|
+
|
|
379
381
|
|
|
380
382
|
return output
|
|
381
383
|
import torch
|
|
382
384
|
import torch.nn as nn
|
|
383
385
|
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class FBSNNNetwork(nn.Module):
|
|
389
|
+
def __init__(
|
|
390
|
+
self,
|
|
391
|
+
layersize: list[int]
|
|
392
|
+
):
|
|
393
|
+
"""
|
|
394
|
+
Initializes a neural network with multiple blocks.
|
|
395
|
+
|
|
396
|
+
Args:
|
|
397
|
+
- indim (int): input dimension
|
|
398
|
+
- layersize (List[int]): list of sizes of hidden layers
|
|
399
|
+
- outdim (int): output dimension
|
|
400
|
+
"""
|
|
401
|
+
super(FBSNNNetwork, self).__init__()
|
|
402
|
+
|
|
403
|
+
# initialize first set of layers
|
|
404
|
+
|
|
405
|
+
self.n_layer = len(layersize) - 1
|
|
406
|
+
# create input layer
|
|
407
|
+
|
|
408
|
+
self.layers = nn.ModuleList([])
|
|
409
|
+
# create hidden layers
|
|
410
|
+
for i in range(len(layersize) - 1):
|
|
411
|
+
self.layers.append(nn.Linear(layersize[i], layersize[i + 1]))
|
|
412
|
+
|
|
413
|
+
def forward(
|
|
414
|
+
self,
|
|
415
|
+
x: torch.Tensor) -> torch.Tensor:
|
|
416
|
+
"""
|
|
417
|
+
Passes the input through the neural network.
|
|
418
|
+
|
|
419
|
+
Args:
|
|
420
|
+
- x (torch.Tensor): input tensor
|
|
421
|
+
|
|
422
|
+
Returns:
|
|
423
|
+
- torch.Tensor: output tensor
|
|
424
|
+
"""
|
|
425
|
+
|
|
426
|
+
for i in range(self.n_layer):
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
# apply layer to tensor
|
|
431
|
+
x = self.layers[i](x)
|
|
432
|
+
if i < self.n_layer - 1 :
|
|
433
|
+
x =torch.sin(x)
|
|
434
|
+
|
|
435
|
+
# apply output layer to tensor
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
return x
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
class DeepBSDE(nn.Module):
|
|
442
|
+
def __init__(
|
|
443
|
+
self,
|
|
444
|
+
layersize: list[int]
|
|
445
|
+
):
|
|
446
|
+
"""
|
|
447
|
+
Initializes a neural network with multiple blocks.
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
- indim (int): input dimension
|
|
451
|
+
- layersize (List[int]): list of sizes of hidden layers
|
|
452
|
+
- outdim (int): output dimension
|
|
453
|
+
"""
|
|
454
|
+
super(DeepBSDE, self).__init__()
|
|
455
|
+
|
|
456
|
+
# initialize first set of layers
|
|
457
|
+
|
|
458
|
+
self.n_layer = len(layersize) - 1
|
|
459
|
+
# create input layer
|
|
460
|
+
|
|
461
|
+
self.layers = nn.ModuleList([])
|
|
462
|
+
self.batch_layer = nn.ModuleList([])
|
|
463
|
+
# create hidden layers
|
|
464
|
+
for i in range(len(layersize) - 1):
|
|
465
|
+
self.layers.append(nn.Linear(layersize[i], layersize[i + 1] , bias=False))
|
|
466
|
+
self.batch_layer.append(nn.BatchNorm1d(layersize[i] , eps=1e-06, momentum=0.01))
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
self.batch_layer.append(nn.BatchNorm1d(layersize[-1] , eps=1e-06, momentum=0.01))
|
|
470
|
+
|
|
471
|
+
def forward(
|
|
472
|
+
self,
|
|
473
|
+
x: torch.Tensor) -> torch.Tensor:
|
|
474
|
+
"""
|
|
475
|
+
Passes the input through the neural network.
|
|
476
|
+
|
|
477
|
+
Args:
|
|
478
|
+
- x (torch.Tensor): input tensor
|
|
479
|
+
|
|
480
|
+
Returns:
|
|
481
|
+
- torch.Tensor: output tensor
|
|
482
|
+
"""
|
|
483
|
+
#x = self.batch_layer[0](x)
|
|
484
|
+
for i in range(self.n_layer - 1):
|
|
485
|
+
|
|
486
|
+
# apply layer to tensor
|
|
487
|
+
x = self.layers[i](x)
|
|
488
|
+
#x = self.batch_layer[i+1](x)
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
x =nn.ReLU()(x)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
# apply output layer to tensor
|
|
495
|
+
x = self.layers[-1](x)
|
|
496
|
+
#x = self.batch_layer[-1](x)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
return x
|
|
500
|
+
|
|
501
|
+
|
|
384
502
|
class TimeDependentNetwork(nn.Module):
|
|
385
503
|
def __init__(
|
|
386
504
|
self,
|
|
@@ -406,18 +524,20 @@ class TimeDependentNetwork(nn.Module):
|
|
|
406
524
|
# create input layer
|
|
407
525
|
self.layers.append(Net1(indim, layersize[0]))
|
|
408
526
|
self.time_layer.append(TimeNet(indim))
|
|
409
|
-
self.batch_layer.append(nn.BatchNorm1d(indim))
|
|
410
|
-
self.batch_layer.append(nn.BatchNorm1d(layersize[0]))
|
|
527
|
+
self.batch_layer.append(nn.BatchNorm1d(indim , eps=1e-06, momentum=0.01))
|
|
528
|
+
self.batch_layer.append(nn.BatchNorm1d(layersize[0],eps=1e-06, momentum=0.01))
|
|
411
529
|
|
|
412
530
|
# create hidden layers
|
|
413
531
|
for i in range(len(layersize) - 1):
|
|
414
532
|
self.layers.append(Net1(layersize[i], layersize[i + 1]))
|
|
415
533
|
self.time_layer.append(TimeNet(layersize[i]))
|
|
416
|
-
self.batch_layer.append(nn.BatchNorm1d(layersize[i + 1]))
|
|
534
|
+
self.batch_layer.append(nn.BatchNorm1d(layersize[i + 1] , eps=1e-06, momentum=0.01))
|
|
417
535
|
|
|
418
536
|
# create output layer
|
|
419
537
|
self.time_layer.append(TimeNet(outdim))
|
|
420
538
|
self.linear = nn.Linear(layersize[-1], outdim)
|
|
539
|
+
self.batch_layer.append(nn.BatchNorm1d(outdim , eps=1e-06, momentum=0.01))
|
|
540
|
+
|
|
421
541
|
|
|
422
542
|
def forward(
|
|
423
543
|
self,
|
|
@@ -433,21 +553,23 @@ class TimeDependentNetwork(nn.Module):
|
|
|
433
553
|
Returns:
|
|
434
554
|
- torch.Tensor: output tensor
|
|
435
555
|
"""
|
|
436
|
-
|
|
437
556
|
for i in range(self.n_layer):
|
|
438
557
|
# apply time-based weights to input tensor
|
|
439
558
|
time = self.time_layer[i](torch.cat((t, t**2, t**3, torch.exp(t)), 1))
|
|
559
|
+
x = self.batch_layer[i](x)
|
|
560
|
+
|
|
440
561
|
|
|
441
562
|
x = x * (1 + time)
|
|
442
|
-
# x = self.batch_layer[i](x)
|
|
443
563
|
|
|
444
564
|
# apply layer to tensor
|
|
445
565
|
x = self.layers[i](x)
|
|
446
|
-
|
|
566
|
+
|
|
567
|
+
x = torch.sin(x)
|
|
447
568
|
|
|
448
569
|
# apply output layer to tensor
|
|
449
570
|
|
|
450
571
|
x = self.linear(x)
|
|
572
|
+
#x = self.batch_layer[-1](x)
|
|
451
573
|
|
|
452
574
|
return x
|
|
453
575
|
|