sdevpy 0.1.2__tar.gz → 0.1.4__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.
Files changed (56) hide show
  1. {sdevpy-0.1.2 → sdevpy-0.1.4}/PKG-INFO +1 -1
  2. {sdevpy-0.1.2 → sdevpy-0.1.4}/pyproject.toml +3 -2
  3. sdevpy-0.1.4/src/sdevpy/__init__.py +1 -0
  4. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/analytics/fbsabr.py +7 -7
  5. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/analytics/mcheston.py +1 -0
  6. sdevpy-0.1.4/src/sdevpy/machinelearning/datasets.py +78 -0
  7. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/maths/metrics.py +9 -0
  8. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/projects/stovol/stovolgen.py +27 -12
  9. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/projects/stovol/stovoltrain.py +55 -41
  10. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/test.py +111 -11
  11. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/tools/filemanager.py +21 -16
  12. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/tools/timegrids.py +20 -4
  13. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/volsurfacegen/fbsabrgenerator.py +7 -12
  14. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/volsurfacegen/mchestongenerator.py +43 -34
  15. sdevpy-0.1.4/src/sdevpy/volsurfacegen/mcsabrgenerator.py +63 -0
  16. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/volsurfacegen/mczabrgenerator.py +26 -43
  17. sdevpy-0.1.2/src/sdevpy/volsurfacegen/mcsabrgenerator.py → sdevpy-0.1.4/src/sdevpy/volsurfacegen/sabrgenerator.py +78 -81
  18. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/volsurfacegen/smilegenerator.py +31 -12
  19. sdevpy-0.1.4/src/sdevpy/volsurfacegen/stovolfactory.py +38 -0
  20. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy.egg-info/PKG-INFO +1 -1
  21. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy.egg-info/SOURCES.txt +0 -1
  22. sdevpy-0.1.4/src/sdevpy.egg-info/requires.txt +6 -0
  23. sdevpy-0.1.2/src/sdevpy/__init__.py +0 -1
  24. sdevpy-0.1.2/src/sdevpy/machinelearning/datasets.py +0 -32
  25. sdevpy-0.1.2/src/sdevpy/projects/stovol/xsabrfit.py +0 -255
  26. sdevpy-0.1.2/src/sdevpy/volsurfacegen/sabrgenerator.py +0 -282
  27. sdevpy-0.1.2/src/sdevpy/volsurfacegen/stovolfactory.py +0 -44
  28. sdevpy-0.1.2/src/sdevpy.egg-info/requires.txt +0 -3
  29. {sdevpy-0.1.2 → sdevpy-0.1.4}/LICENSE +0 -0
  30. {sdevpy-0.1.2 → sdevpy-0.1.4}/README.md +0 -0
  31. {sdevpy-0.1.2 → sdevpy-0.1.4}/setup.cfg +0 -0
  32. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/analytics/bachelier.py +0 -0
  33. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/analytics/black.py +0 -0
  34. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/analytics/mcsabr.py +0 -0
  35. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/analytics/mczabr.py +0 -0
  36. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/analytics/sabr.py +0 -0
  37. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/machinelearning/callbacks.py +0 -0
  38. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/machinelearning/learningmodel.py +0 -0
  39. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/machinelearning/learningschedules.py +0 -0
  40. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/machinelearning/topology.py +0 -0
  41. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/maths/interpolations.py +0 -0
  42. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/maths/optimization.py +0 -0
  43. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/maths/rand.py +0 -0
  44. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/projects/datafiles.py +0 -0
  45. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/projects/pinns/ernst_pinns.py +0 -0
  46. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/projects/pinns/pinns.py +0 -0
  47. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/projects/pinns/pinns_worst_of.py +0 -0
  48. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/projects/stovol/stovolplot.py +0 -0
  49. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/settings.py +0 -0
  50. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/tools/clipboard.py +0 -0
  51. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/tools/constants.py +0 -0
  52. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/tools/jsonmanager.py +0 -0
  53. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy/tools/timer.py +0 -0
  54. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy.egg-info/dependency_links.txt +0 -0
  55. {sdevpy-0.1.2 → sdevpy-0.1.4}/src/sdevpy.egg-info/top_level.txt +0 -0
  56. {sdevpy-0.1.2 → sdevpy-0.1.4}/tests/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sdevpy
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Python package for Machine Learning in Finance
5
5
  Author-email: Sebastien Gurrieri <sebgur@gmail.com>
6
6
  Project-URL: Git page, https://github.com/sebgur/SDev.Python
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sdevpy"
7
- version = "0.1.2"
7
+ version = "0.1.4"
8
8
  authors = [
9
9
  { name="Sebastien Gurrieri", email="sebgur@gmail.com" },
10
10
  ]
@@ -17,7 +17,8 @@ classifiers = [
17
17
  "Operating System :: OS Independent",
18
18
  ]
19
19
  dependencies = [
20
- "pandas","pyperclip","py_vollib"
20
+ "pandas","pyperclip","py_vollib","numpy","tensorflow",
21
+ "scikit-learn"
21
22
  ]
22
23
 
23
24
  [project.urls]
@@ -0,0 +1 @@
1
+ __version__ = '0.1.4'
@@ -109,15 +109,15 @@ def calculate_fbsabr_alpha(ln_vol, fwd, beta):
109
109
  return ln_vol * abs_f ** (1.0 - beta)
110
110
 
111
111
  if __name__ == "__main__":
112
- EXPIRIES = [0.05, 0.10, 0.25, 0.5]
112
+ EXPIRIES = [3.0, 8.0, 13, 19, 22, 31, 34]
113
113
  NSTRIKES = 50
114
- FWD = -0.005
115
- SHIFT = 0.03
114
+ FWD = 0.016132
115
+ SHIFT = 0.00
116
116
  SFWD = FWD + SHIFT
117
117
  IS_CALL = False
118
118
  ARE_CALLS = [IS_CALL] * NSTRIKES
119
119
  ARE_CALLS = [ARE_CALLS] * len(EXPIRIES)
120
- LNVOL = 0.25
120
+ LNVOL = 0.48
121
121
  # Spread method
122
122
  # SPREADS = np.linspace(-200, 200, NSTRIKES)
123
123
  # SPREADS = np.asarray([SPREADS] * len(EXPIRIES))
@@ -134,11 +134,11 @@ if __name__ == "__main__":
134
134
  STRIKES = SSTRIKES - SHIFT
135
135
  XAXIS = STRIKES
136
136
 
137
- PARAMETERS = {'LnVol': LNVOL, 'Beta': 0.1, 'Nu': 0.50, 'Rho': -0.25}
137
+ PARAMETERS = {'LnVol': LNVOL, 'Beta': 0.5, 'Nu': 0.66, 'Rho': 0.48}
138
138
  NUM_MC = 100 * 1000
139
139
  POINTS_PER_YEAR = 25
140
- # SCHEME = 'Andersen'
141
- SCHEME = 'Euler'
140
+ SCHEME = 'Andersen'
141
+ # SCHEME = 'Euler'
142
142
 
143
143
  # Calculate MC prices
144
144
  mc_timer = timer.Stopwatch("MC")
@@ -28,6 +28,7 @@ def price(expiries, strikes, are_calls, fwd, parameters, num_mc=10000, points_pe
28
28
  time_grid = time_grid_builder.complete_grid()
29
29
  num_factors = 2
30
30
 
31
+
31
32
  # Find payoff times
32
33
  is_payoff = np.in1d(time_grid, expiries)
33
34
 
@@ -0,0 +1,78 @@
1
+ """ Dataset preparation for training """
2
+ import os
3
+ import numpy as np
4
+ import pandas as pd
5
+ from sdevpy.tools import filemanager
6
+
7
+
8
+ def prepare_sets(inputs, outputs, train_percent):
9
+ """ Split input and output datasets into training and test datasets split
10
+ according to specified percentage to put in the training set """
11
+ data_size = inputs.shape[0]
12
+ if outputs.shape[0] != data_size:
13
+ raise RuntimeError("Incompatible sizes between inputs and outputs")
14
+
15
+ train_size = int(data_size * train_percent)
16
+
17
+ train_inputs = inputs[0:train_size]
18
+ train_outputs = outputs[0:train_size]
19
+ test_inputs = inputs[train_size:data_size]
20
+ test_outputs = outputs[train_size:data_size]
21
+
22
+ return train_inputs, train_outputs, test_inputs, test_outputs
23
+
24
+ def retrieve_data(folder, num_samples, shuffle=True, sep='\t', export_file=""):
25
+ """ Use all files in folder to create a dataset, shuffle its data,
26
+ extract num_samples from it and return dataframe """
27
+
28
+ # Set extension
29
+ if sep == '\t':
30
+ extension = ".tsv"
31
+ elif sep == ',':
32
+ extension = ".csv"
33
+ else:
34
+ raise RuntimeError("Unknown text file separation")
35
+
36
+ # Merge content of folder in single dataframe
37
+ files = filemanager.list_files(folder, [extension])
38
+ df = pd.DataFrame()
39
+ for f in files:
40
+ new_df = pd.read_csv(os.path.join(folder, f), sep=sep)
41
+ df = pd.concat([df, new_df])
42
+
43
+ if shuffle:
44
+ df = df.sample(frac=1)
45
+
46
+ # Clip num_samples
47
+ df = clip_dataframe(df, num_samples)
48
+
49
+ # If export_file is not empty, export to file
50
+ if export_file != "":
51
+ df.to_csv(export_file, sep=sep, index=False)
52
+
53
+ return df
54
+
55
+ def clip_dataframe(df, size):
56
+ """ Clip dataframe beyond specified size"""
57
+ df_size = len(df.index)
58
+ if df_size <= size:
59
+ return df
60
+ else:
61
+ return df.iloc[range(0, size)]
62
+
63
+
64
+ if __name__ == "__main__":
65
+ INPUTS = np.asarray([[1, 1], [2, 2], [3, 3], [4, 4], [5, 5]])
66
+ OUTPUTS = np.asarray([[1], [2], [3], [4], [5]])
67
+ train_x, train_y, test_x, test_y = prepare_sets(INPUTS, OUTPUTS, 0.80)
68
+ print(train_x)
69
+ print(train_y)
70
+ print(test_x)
71
+ print(test_y)
72
+
73
+ # Test merging
74
+ FOLDER = r"C:\temp\sdevpy\stovol\samples\test"
75
+ NUM_SAMPLES = 4
76
+ DATA_FILE = r"C:\temp\sdevpy\stovol\samples\test.tsv"
77
+ DATA_DF = retrieve_data(FOLDER, NUM_SAMPLES, export_file=DATA_FILE, shuffle=True)
78
+ print(DATA_DF)
@@ -8,6 +8,15 @@ def rmse(set1, set2):
8
8
  """ Root Mean Squared Error """
9
9
  return np.sqrt(mean_squared_error(set1, set2))
10
10
 
11
+ def bps_rmse(y_true, y_ref):
12
+ """ RMSE in bps """
13
+ return 10000.0 * rmse(y_true, y_ref)
14
+
15
+ # Tensorflow versions
11
16
  def tf_rmse(y_true, y_pred):
12
17
  """ Root Mean Squared Error in tensorflow """
13
18
  return tf.sqrt(tf.math.reduce_mean(tf.square(y_true - y_pred)))
19
+
20
+ def tf_bps_rmse(y_true, y_ref):
21
+ """ RMSE in bps in tensorflow """
22
+ return 10000.0 * tf_rmse(y_true, y_ref)
@@ -4,21 +4,21 @@
4
4
  import os
5
5
  from sdevpy.volsurfacegen import stovolfactory
6
6
  from sdevpy import settings
7
- from sdevpy.tools.filemanager import check_directory
7
+ from sdevpy.tools import filemanager
8
8
  from sdevpy.tools.timer import Stopwatch
9
9
 
10
10
 
11
11
  # ################ Runtime configuration ##########################################################
12
12
  # MODEL_TYPE = "SABR"
13
- # MODEL_TYPE = "ShiftedSABR"
14
- # MODEL_TYPE = "McShiftedSABR"
15
- MODEL_TYPE = "FbSABR"
16
- # MODEL_TYPE = "McShiftedZABR"
17
- # MODEL_TYPE = "McShiftedHeston"
18
- NUM_SAMPLES = 400 * 1000
13
+ # MODEL_TYPE = "McSABR"
14
+ # MODEL_TYPE = "FbSABR"
15
+ # MODEL_TYPE = "McZABR"
16
+ MODEL_TYPE = "McHeston"
17
+ SHIFT = 0.03
18
+ NUM_SAMPLES = 1 * 1000
19
19
  # The 4 parameters below are only relevant for models whose reference is calculated by MC
20
20
  NUM_EXPIRIES = 10
21
- SURFACE_SIZE = 50
21
+ NUM_STRIKES = 5
22
22
  NUM_MC = 100 * 1000 # 100 * 1000
23
23
  POINTS_PER_YEAR = 25 # 25
24
24
  SEED = 42# [123456789, 6789, 9191, 888, 4321, 100, 4444, 72, 1234, 42]
@@ -28,21 +28,36 @@ project_folder = os.path.join(settings.WORKFOLDER, "stovol")
28
28
  print("> Project folder: " + project_folder)
29
29
  data_folder = os.path.join(project_folder, "samples")
30
30
  print("> Data folder: " + data_folder)
31
- check_directory(data_folder)
31
+ filemanager.check_directory(data_folder)
32
32
  print("> Chosen model: " + MODEL_TYPE)
33
33
  data_file = os.path.join(data_folder, MODEL_TYPE + "_samples.tsv")
34
34
 
35
- # ################ Select model ###############################################################
36
- generator = stovolfactory.set_generator(MODEL_TYPE, NUM_EXPIRIES, SURFACE_SIZE, NUM_MC,
35
+ # ################ Select model ###################################################################
36
+ generator = stovolfactory.set_generator(MODEL_TYPE, SHIFT, NUM_EXPIRIES, NUM_STRIKES, NUM_MC,
37
37
  POINTS_PER_YEAR, SEED)
38
38
 
39
+ # ################ Select training ranges #########################################################
40
+ # # SABR
41
+ # RANGES = {'Ttm': [1.0 / 12.0, 35.0], 'K': [0.01, 0.99], 'F': [-0.009, 0.041], 'LnVol': [0.05, 0.5],
42
+ # 'Beta': [0.1, 0.9], 'Nu': [0.1, 1.0], 'Rho': [-0.6, 0.6]}
43
+ # # ZABR
44
+ # RANGES = {'Ttm': [1.0 / 12.0, 35.0], 'K': [0.01, 0.99], 'F': [-0.009, 0.041], 'LnVol': [0.05, 0.25],
45
+ # 'Beta': [0.49, 0.51], 'Nu': [0.20, 0.80], 'Rho': [-0.4, 0.4],
46
+ # 'Gamma': [0.10, 0.9]}
47
+ # Heston
48
+ RANGES = {'Ttm': [1.0 / 12.0, 35.0], 'K': [0.01, 0.99], 'F': [-0.009, 0.041], 'LnVol': [0.05, 0.25],
49
+ 'Kappa': [0.25, 4.00], 'Theta': [0.05**2, 0.25**2], 'Xi': [0.10, 0.50],
50
+ 'Rho': [-0.40, 0.40]}
51
+
39
52
  # ################ Generate dataset ###############################################################
40
53
  print(">> Generate dataset")
41
54
 
42
55
  print(f"> Generate {NUM_SAMPLES:,} price samples")
43
56
  timer_gen = Stopwatch("Generating Samples")
44
57
  timer_gen.trigger()
45
- data_df = generator.generate_samples(NUM_SAMPLES)
58
+ data_df = generator.generate_samples(NUM_SAMPLES, RANGES)
59
+ # full_data_file = os.path.join(data_folder, MODEL_TYPE + "_samples_full.tsv")
60
+ # generator.to_file(data_df, full_data_file)
46
61
  timer_gen.stop()
47
62
 
48
63
  print("> Convert to normal vol and cleanse data")
@@ -13,31 +13,36 @@ from sdevpy.machinelearning.topology import compose_model
13
13
  from sdevpy.machinelearning.learningmodel import LearningModel, load_learning_model
14
14
  from sdevpy.machinelearning.learningschedules import FlooredExponentialDecay
15
15
  from sdevpy.machinelearning.callbacks import RefCallback
16
- from sdevpy.machinelearning.datasets import prepare_sets
17
- from sdevpy.tools.filemanager import check_directory
16
+ from sdevpy.machinelearning import datasets
17
+ from sdevpy.tools import filemanager
18
18
  from sdevpy.tools.timer import Stopwatch
19
19
  from sdevpy.tools import clipboard
20
- from sdevpy.maths.metrics import rmse, tf_rmse
20
+ from sdevpy.maths.metrics import bps_rmse, tf_bps_rmse
21
21
  from sdevpy.volsurfacegen.stovolfactory import set_generator
22
22
  from sdevpy.projects.stovol import stovolplot as xplt
23
23
 
24
+
25
+ # Implement DOWNLOAD_DATASET for TRAIN = True
26
+ # Create Colab to generate, Colab to train
24
27
  # Fine-train models
25
- # Use type in json to know which type to instantiate
26
- # Lazy instantiation from remote/name code
27
28
  # Store data in Kaggle
28
29
 
29
30
  # ################ Runtime configuration ##########################################################
30
- # MODEL_TYPE = "SABR"
31
- # MODEL_TYPE = "ShiftedSABR"
32
- # MODEL_TYPE = "McShiftedSABR"
33
- MODEL_TYPE = "FbSABR"
34
- # MODEL_TYPE = "McShiftedZABR"
35
- # MODEL_TYPE = "McShiftedHeston"
31
+ MODEL_TYPE = "SABR"
32
+ # MODEL_TYPE = "McSABR"
33
+ # MODEL_TYPE = "FbSABR"
34
+ # MODEL_TYPE = "McZABR"
35
+ # MODEL_TYPE = "McHeston"
36
+ MODEL_ID = "SABR_3L_64n" # Pre-trained model ID (we can pre-train several versions)
37
+ SHIFT = 0.03
36
38
  USE_TRAINED = True
39
+ DOWNLOAD_MODELS = True # Only used when USE_TRAINED is True
40
+ DOWNLOAD_DATASETS = True # Use when already created/downloaded
37
41
  TRAIN = False
38
42
  if USE_TRAINED is False and TRAIN is False:
39
43
  raise RuntimeError("When not using pre-trained models, a new model must be trained")
40
44
 
45
+ NUM_SAMPLES = 500 * 1000 # Number of samples to read from sample files
41
46
  TRAIN_PERCENT = 0.90 # Proportion of dataset used for training (rest used for test)
42
47
  EPOCHS = 100
43
48
  BATCH_SIZE = 1000
@@ -47,35 +52,40 @@ NUM_MC = 100 * 1000 # 100 * 1000
47
52
  POINTS_PER_YEAR = 25 # 25
48
53
 
49
54
  print(">> Set up runtime configuration")
55
+ print("> Chosen model type: " + MODEL_TYPE)
56
+ if USE_TRAINED:
57
+ print("> Pre-trained model ID: " + MODEL_ID)
58
+
50
59
  project_folder = os.path.join(settings.WORKFOLDER, "stovol")
51
60
  print("> Project folder: " + project_folder)
52
- data_folder = os.path.join(project_folder, "samples")
61
+ sample_folder = os.path.join(project_folder, "samples")
62
+ data_folder = os.path.join(sample_folder, MODEL_TYPE)
53
63
  print("> Data folder: " + data_folder)
54
- check_directory(data_folder)
55
- print("> Chosen model: " + MODEL_TYPE)
56
- data_file = os.path.join(data_folder, MODEL_TYPE + "_samples.tsv")
64
+ data_file = os.path.join(sample_folder, MODEL_TYPE + "_samples.tsv")
65
+ print("> Data file: " + data_file)
57
66
  model_folder = os.path.join(project_folder, "models")
58
67
  print("> Model folder: " + model_folder)
59
68
 
60
- # ################ Helper functions ###############################################################
61
- def bps_rmse(y_true, y_ref):
62
- """ RMSE in bps """
63
- return 10000.0 * rmse(y_true, y_ref)
69
+ if USE_TRAINED and DOWNLOAD_MODELS:
70
+ url = 'https://github.com/sebgur/SDev.Python/raw/main/models/stovol/stovol.zip'
71
+ print("> Downloading and unzipping models from: " + url)
72
+ filemanager.download_unzip(url, model_folder)
64
73
 
65
- def tf_bps_rmse(y_true, y_ref):
66
- """ RMSE in bps in tensorflow """
67
- return 10000.0 * tf_rmse(y_true, y_ref)
74
+ if DOWNLOAD_DATASETS:
75
+ print("> Downloading datasets from: ")
68
76
 
69
77
  # ################ Select generator ###############################################################
70
78
  # Select generator. The number of expiries and surface size are irrelevant as here we do not
71
79
  # generate sample data but read it from files. Number of MC and points per year are required
72
80
  # to calculate the reference values against which we can validate the model.
73
- generator = set_generator(MODEL_TYPE, num_mc=NUM_MC, points_per_year=POINTS_PER_YEAR)
81
+ generator = set_generator(MODEL_TYPE, shift=SHIFT, num_mc=NUM_MC, points_per_year=POINTS_PER_YEAR)
74
82
 
75
83
  # ################ Prepare datasets ###############################################################
76
84
  # Datasets are always read, as even if we don't train, we're still going to evaluate the
77
85
  # performance of the pre-trained model
78
86
  print(">> Preparing datasets")
87
+ # Retrieve data from dataset folder
88
+ datasets.retrieve_data(data_folder, NUM_SAMPLES, shuffle=True, export_file=data_file)
79
89
  # Retrieve dataset
80
90
  print("> Reading dataset from file: " + data_file)
81
91
  x_set, y_set, data_df = generator.retrieve_datasets(data_file, shuffle=True)
@@ -88,13 +98,15 @@ print(data_df.head())
88
98
  # Split into training and test sets
89
99
  TRS = TRAIN_PERCENT * 100
90
100
  print(f"> Splitting between training set ({TRS:.2f}%) and test set ({100 - TRS:.2f}%)")
91
- x_train, y_train, x_test, y_test = prepare_sets(x_set, y_set, TRAIN_PERCENT)
101
+ x_train, y_train, x_test, y_test = datasets.prepare_sets(x_set, y_set, TRAIN_PERCENT)
102
+ print(f"> Training set size: {x_train.shape[0]:,}")
103
+ print(f"> Testing set size: {x_test.shape[0]:,}")
92
104
 
93
105
  # ################ Compose/Load the model #########################################################
94
106
  # Compose new model or load pre-trained one
95
107
  if USE_TRAINED:
96
108
  print(">> Loading pre-trained model")
97
- model_folder_name = os.path.join(model_folder, MODEL_TYPE)
109
+ model_folder_name = os.path.join(model_folder, MODEL_ID)
98
110
  print("> Loading pre-trained model from: " + model_folder_name)
99
111
  model = load_learning_model(model_folder_name)
100
112
  keras_model = model.model
@@ -138,26 +150,19 @@ if TRAIN:
138
150
  for field, value in optim_fields.items():
139
151
  print("> ", field, ":", value)
140
152
 
141
-
142
153
  # Compile
143
154
  print("> Compile model")
144
155
  keras_model.compile(loss=tf_bps_rmse, optimizer=optimizer)
145
156
 
146
-
147
157
  # Callbacks
148
158
  EPOCH_SAMPLING = 5
149
159
  callback = RefCallback(x_test, y_test, bps_rmse, optimizer=optimizer,
150
160
  epoch_sampling=EPOCH_SAMPLING)
151
- # callback = None
152
- # callback = SDevPyCallback(optimizer=optimizer, epoch_sampling=EPOCH_SAMPLING)
153
161
 
154
162
  # Train the network
155
163
  print(">> Training ANN model")
156
164
  trn_timer = Stopwatch("Training")
157
165
  trn_timer.trigger()
158
- # shuffled_indices = np.random.permutation(x_train.shape[0])
159
- # x_train = x_train[shuffled_indices]
160
- # y_train = y_train[shuffled_indices]
161
166
  model.train(x_train, y_train, EPOCHS, BATCH_SIZE, callback)
162
167
  trn_timer.stop()
163
168
  trn_timer.print()
@@ -177,22 +182,23 @@ print(">> Analyse results")
177
182
  # Check performance
178
183
  train_pred = model.predict(x_train)
179
184
  train_rmse = bps_rmse(train_pred, y_train)
180
- print(f"RMSE(nvol) on training set: {train_rmse:,.2f}")
185
+ print(f"> RMSE(nvol) on training set: {train_rmse:,.2f}")
181
186
 
182
187
  test_pred = model.predict(x_test)
183
188
  test_rmse = bps_rmse(test_pred, y_test)
184
- print(f"RMSE(nvol) on test set: {test_rmse:,.2f}")
189
+ print(f"> RMSE(nvol) on test set: {test_rmse:,.2f}")
185
190
 
186
191
  # Generate strike spread axis
187
192
  if SHOW_VOL_CHARTS:
193
+ print("> Choosing a sample parameter set to display chart")
188
194
  NUM_STRIKES = 100
189
195
  PARAMS = { 'LnVol': 0.20, 'Beta': 0.5, 'Nu': 0.55, 'Rho': -0.25, 'Gamma': 0.7, 'Kappa': 1.0,
190
196
  'Theta': 0.05, 'Xi': 0.50 }
191
197
  FWD = 0.028
192
198
 
193
199
  # Any number of expiries can be calculated, but for optimum display choose no more than 6
194
- EXPIRIES = np.asarray([0.125, 0.250, 0.5, 1.00, 2.0, 5.0]).reshape(-1, 1)
195
- # EXPIRIES = np.asarray([0.25, 0.50, 1.0, 5.00, 10.0, 30.0]).reshape(-1, 1)
200
+ # EXPIRIES = np.asarray([0.125, 0.250, 0.5, 1.00, 2.0, 5.0]).reshape(-1, 1)
201
+ EXPIRIES = np.asarray([0.25, 0.50, 1.0, 5.00, 10.0, 30.0]).reshape(-1, 1)
196
202
  NUM_EXPIRIES = EXPIRIES.shape[0]
197
203
  METHOD = 'Percentiles'
198
204
  PERCENTS = np.linspace(0.01, 0.99, num=NUM_STRIKES)
@@ -204,15 +210,23 @@ if SHOW_VOL_CHARTS:
204
210
  # ARE_CALLS = [[False if s < FWD else True for s in expks] for expks in strikes] # Puts/calls
205
211
  # print(ARE_CALLS)
206
212
 
207
- print("Calculating chart surface with reference model")
213
+ print("> Calculating chart surface with reference model")
214
+ timer_ref = Stopwatch("Reference surface calculation")
215
+ timer_ref.trigger()
208
216
  ref_prices = generator.price_surface_ref(EXPIRIES, strikes, ARE_CALLS, FWD, PARAMS)
209
- # print(ref_prices.shape)
217
+ timer_ref.stop()
210
218
  # clipboard.export2d(ref_prices)
211
- print("Calculating chart surface with trained model")
219
+ print("> Calculating chart surface with trained model")
220
+ timer_mod = Stopwatch("Model surface calculation")
221
+ timer_mod.trigger()
212
222
  mod_prices = generator.price_surface_mod(model, EXPIRIES, strikes, ARE_CALLS, FWD, PARAMS)
213
- # print(mod_prices.shape)
223
+ timer_mod.stop()
214
224
  # clipboard.export2d(mod_prices)
215
- print(f"Ref-Mod RMSE(price): {bps_rmse(ref_prices, mod_prices):.2f}")
225
+ print(f"> Ref-Mod RMSE(price): {bps_rmse(ref_prices, mod_prices):.2f}")
226
+
227
+ # Display timers
228
+ timer_ref.print()
229
+ timer_mod.print()
216
230
 
217
231
  # Available tranforms: Price, ShiftedBlackScholes, Bachelier
218
232
  TITLE = f"{MODEL_TYPE} smile sections, forward={FWD*100:.2f}"#,%\n parameters={PARAMS}"
@@ -1,16 +1,116 @@
1
1
  """ Just to test things """
2
2
  # import tensorflow as tf
3
- import numpy as np
4
- import scipy.stats as sp
5
- import json
6
- import matplotlib.pyplot as plt
7
- # from maths.metrics import rmse
8
- # import projects.xsabr_fit.sabrgenerator as sabr
9
-
10
- strikes = [1, 2, 3, 4, 5]
11
- fwd = 2.5
12
- are_calls = [False if s < fwd else True for s in strikes]
13
- print(are_calls)
3
+ # import numpy as np
4
+ # import scipy.stats as sp
5
+ # import json
6
+ # import matplotlib.pyplot as plt
7
+ import requests, zipfile
8
+ import io
9
+ import pandas as pd
10
+ from io import BytesIO
11
+
12
+ # URL = 'https://drive.google.com/file/d/10dKi82fW2arlKnOahNv9i5igfiydwMnc/view?usp=sharing'
13
+
14
+
15
+ # def download_file_from_google_drive(id, destination):
16
+ # # URL = "https://docs.google.com/uc?export=download"
17
+
18
+ # session = requests.Session()
19
+
20
+ # print(URL)
21
+ # print(id)
22
+ # response = session.get(URL, params = { 'id' : id }, stream = True)
23
+ # print(response)
24
+ # token = get_confirm_token(response)
25
+ # print(token)
26
+
27
+ # if token:
28
+ # params = { 'id' : id, 'confirm' : token }
29
+ # response = session.get(URL, params = params, stream = True)
30
+
31
+ # save_response_content(response, destination)
32
+
33
+ # def get_confirm_token(response):
34
+ # for key, value in response.cookies.items():
35
+ # if key.startswith('download_warning'):
36
+ # return value
37
+
38
+ # return None
39
+
40
+ # def save_response_content(response, destination):
41
+ # CHUNK_SIZE = 32768
42
+
43
+ # with open(destination, "wb") as f:
44
+ # for chunk in response.iter_content(CHUNK_SIZE):
45
+ # if chunk: # filter out keep-alive new chunks
46
+ # f.write(chunk)
47
+
48
+
49
+
50
+ # id = '10dKi82fW2arlKnOahNv9i5igfiydwMnc'
51
+
52
+ # destination_ = ''
53
+
54
+ # download_file_from_google_drive(id, destination_)
55
+
56
+ # sample_url = 'https://1drv.ms/u/s!AivreF7B9rL4kK8Hx1vT4PRjtbE1iA?e=fxM7Kx' # OneDrive
57
+
58
+ # req = requests.get(sample_url)
59
+
60
+ # # Extract
61
+ # zipfile = zipfile.ZipFile(BytesIO(req.content))
62
+ # zipfile.extractall('New Folder')
63
+
64
+ # url = 'https://github.com/sebgur/SDev.Python/raw/main/models/stovol/SABR.zip'
65
+
66
+ # MODEL_NAME = 'SABR'
67
+ # OUPUT_ROOT = r'C:\temp\sdevpy\stovol\models'
68
+
69
+ # base_url = 'https://github.com/sebgur/SDev.Python/raw/main/models/stovol/'
70
+ # model_url = base_url + MODEL_NAME + ".zip"
71
+
72
+ # req = requests.get(model_url)
73
+
74
+ # filename = url.split('/')[-1]
75
+ # print("Downloading: " + filename)
76
+
77
+ # # Download
78
+ # with open(filename,'wb') as output_file:
79
+ # output_file.write(req.content)
80
+ # print('Downloading Completed')
81
+
82
+ # # Extract
83
+ # zipfile = zipfile.ZipFile(BytesIO(req.content))
84
+ # zipfile.extractall(OUPUT_ROOT)
85
+
86
+
87
+ # url = "https://raw.githubusercontent.com/sebgur/SDev.Python/main/samples/McHeston_samples.tsv"
88
+
89
+ # https://github.com/sebgur/SDev.Python/blob/main/models/stovol/SABR/config.json
90
+ # https://raw.githubusercontent.com/sebgur/SDev.Python/main/models/stovol/SABR/config.json
91
+
92
+ # https://github.com/sebgur/SDev.Python/tree/main/models/stovol
93
+ # https://raw.githubusercontent.com/sebgur/SDev.Python/main/models/stovol
94
+
95
+ # download = requests.get(url).content
96
+
97
+ # df = pd.read_csv(io.StringIO(download.decode('utf-8')), sep='\t')
98
+ # print(df.head())
99
+
100
+ # parameters = { 'LnVol2': 0.2, 'Beta': 0.5}
101
+
102
+ # # print(parameters['LnVol'])
103
+
104
+ # if 'LnVol' in parameters:
105
+ # print("found it")
106
+ # else:
107
+ # print("boooo")
108
+
109
+
110
+ # strikes = [1, 2, 3, 4, 5]
111
+ # fwd = 2.5
112
+ # are_calls = [False if s < fwd else True for s in strikes]
113
+ # print(are_calls)
14
114
 
15
115
  # num_expiries = 2
16
116
  # num_strikes = 3
@@ -1,9 +1,27 @@
1
1
  """ File management utilities """
2
2
  import os
3
3
  import csv
4
- import winsound
5
- import datetime as dt
4
+ # import datetime as dt
6
5
  import pathlib
6
+ from io import BytesIO
7
+ import zipfile as zf
8
+ import requests
9
+
10
+
11
+ def download_unzip(zip_url, extract_folder, save_file=False):
12
+ """ Download zip file from url and unzip """
13
+ req = requests.get(zip_url, timeout=10)
14
+
15
+ if save_file:
16
+ down_filename = zip_url.split('/')[-1]
17
+ with open(down_filename,'wb') as output_file:
18
+ output_file.write(req.content)
19
+
20
+ with zf.ZipFile(BytesIO(req.content)) as zip_file:
21
+ zip_file.extractall(extract_folder)
22
+
23
+ # zipfile = zf.ZipFile(BytesIO(req.content))
24
+ # zipfile.extractall(extract_folder)
7
25
 
8
26
 
9
27
  def check_directory(path):
@@ -31,6 +49,7 @@ def write_csv(file):
31
49
 
32
50
  # return files
33
51
 
52
+
34
53
  def list_files(path, extensions=None):
35
54
  """ List all files in a path that have the extensions """
36
55
  all_files = os.listdir(path)
@@ -43,17 +62,3 @@ def list_files(path, extensions=None):
43
62
  files.append(f)
44
63
 
45
64
  return files
46
-
47
- def make_a_noise(beep=True):
48
- """ Make a noise """
49
- if beep:
50
- f1 = 500
51
- f2 = 1000
52
- duration = 300
53
- winsound.Beep(f1, duration)
54
- winsound.Beep(f2, duration)
55
- winsound.Beep(f1, duration)
56
-
57
- now = dt.datetime.now()
58
- dt_string = now.strftime("%H:%M:%S, %d/%m/%Y")
59
- print("Closing at ", dt_string)
@@ -24,7 +24,7 @@ class TimeGridBuilder(ABC):
24
24
 
25
25
  def add_grid(self, times):
26
26
  """ Add vector of times """
27
- self.time_grid_.extend(times)
27
+ self.time_grid_.extend(times.reshape(-1))
28
28
 
29
29
  def refine(self):
30
30
  """ Add a fine grid to the current grid """
@@ -82,8 +82,24 @@ if __name__ == "__main__":
82
82
  settlement = date(2026, 1, 24)
83
83
  builder = SimpleTimeGridBuilder(5)
84
84
  builder.add_dates(base, [fixing, settlement, expiry, monitor, settlement])
85
- print(builder.time_grid_)
85
+ # print(builder.time_grid_)
86
86
  builder.refine()
87
- print(builder.time_grid_)
87
+ # print(builder.time_grid_)
88
88
  builder.clean()
89
- print(builder.time_grid_)
89
+ # print(builder.time_grid_)
90
+
91
+ # Test MC situation
92
+ time_grid_builder = SimpleTimeGridBuilder(points_per_year=5)
93
+ EXPIRIES = np.asarray([5.0, 1.0, 0.125, 0.250, 0.5]).reshape(-1, 1)
94
+ print(EXPIRIES)
95
+ time_grid_builder.add_grid(EXPIRIES)
96
+ print(time_grid_builder.time_grid_)
97
+ print("refine")
98
+ time_grid_builder.refine()
99
+ print(time_grid_builder.time_grid_)
100
+ print("clean")
101
+ time_grid_builder.clean()
102
+ tg = time_grid_builder.time_grid_
103
+ print(tg)
104
+ # time_grid = time_grid_builder.complete_grid()
105
+