aboutsummaryrefslogtreecommitdiffstats
path: root/gen.py
diff options
context:
space:
mode:
Diffstat (limited to 'gen.py')
-rw-r--r--gen.py243
1 files changed, 243 insertions, 0 deletions
diff --git a/gen.py b/gen.py
new file mode 100644
index 0000000..149e287
--- /dev/null
+++ b/gen.py
@@ -0,0 +1,243 @@
+#! /usr/bin/env python3
+# author : S. Mandalia
+# shivesh.mandalia@outlook.com
+#
+# date : May 20, 2020
+
+
+"""
+Exotic options by Monte Carlo.
+
+Generate fake data.
+
+"""
+
+import random
+from typing import List
+
+import numpy as np
+
+from utils.engine import PricingEngine
+from utils.path import PathGenerator
+from utils.payoff import AsianArithmeticPayOff, DiscreteBarrierPayOff
+from utils.payoff import VanillaPayOff
+
+
+__all__ = ['vanilla', 'asian', 'barrier']
+
+
+NGEN = 13
+# NGEN = 10
+NTRIALS = 1e5
+
+
+def vanilla() -> None:
+ """Generate Vanilla option fake data."""
+ outfile = './vanilla.csv'
+
+ with open(outfile, 'w') as f:
+ s = 'ID,Spot,Strike,Risk-Free Rate,Years to Expiry,Volatility,' \
+ 'Option Right,Price\n'
+ f.write(s)
+
+ idx = 0
+ for ndx in range(NGEN):
+ if (ndx + 1) % 10 == 0:
+ print('{0} / {1}'.format(ndx + 1, NGEN))
+
+ for right in ('Call', 'Put'):
+ S, K, T, r, vol = np.random.random(5)
+ S *= 300
+ K *= 300
+ r = r * 1E-2 - 5E-3
+ T *= 3
+ vol += 1E-4
+
+ path = PathGenerator(S=S, r=r, div=0., vol=vol)
+ payoff = VanillaPayOff(K=K, option_right=right)
+ engine = PricingEngine(payoff=payoff, path=path)
+
+ # Price
+ result = engine.price(T=[0, T], ntrials=NTRIALS)
+ s = '{0},{1:.6g},{2:.6g},{3:.6g},{4:.6g},{5:.6g},{6},' \
+ '{7:.6g}\n'.format(
+ idx, S, K, r, T, vol, right, result.price
+ )
+ f.write(s)
+ idx += 1
+
+
+def asian() -> None:
+ """Generate Asian option fake data."""
+ outfile = './asian.csv'
+
+ with open(outfile, 'w') as f:
+ s = 'ID,Spot,Strike,Risk-Free Rate,Years to Expiry,Volatility,' \
+ 'Option Right,Averaging Days,Price\n'
+ f.write(s)
+
+ idx = 0
+ for right in ('Call', 'Put'):
+ idy = 0
+ while idy < NGEN:
+ S, K, T, r, vol = np.random.random(5)
+ S *= 300
+ K *= 300
+ r = r * 1E-2 - 5E-3
+ T *= 1
+ vol += 1E-4
+
+ path = PathGenerator(S=S, r=r, div=0., vol=vol)
+ payoff = AsianArithmeticPayOff(K=K, option_right=right)
+ engine = PricingEngine(payoff=payoff, path=path)
+
+ # (i) an Asian call option with maturity in T year(s) and
+ # 30 days averaging.
+ ad = 30
+ n = int(T * 365 // ad)
+ if n > 1:
+ # f_start = (T * 365 - n * ad)
+ # t = [(x * ad) + f_start for x in range(n + 1)]
+ t = [(x * ad / 365.) for x in range(n + 1)]
+
+ # Price
+ result = engine.price(T=t, ntrials=NTRIALS)
+ if abs(result.price) < 1E-5:
+ continue
+ s = '{0},{1:.6g},{2:.6g},{3:.6g},{4:.6g},{5:.6g},{6},{7},' \
+ '{8:.6g}\n'.format(
+ idx, S, K, r, T, vol, right, ad, result.price
+ )
+ f.write(s)
+ idx += 1
+ idy += 1
+
+ # # (ii) an Asian call option with maturity in T year(s) and
+ # # 90 days averaging.
+ # ad = 90
+ # n = int(T * 365 // ad)
+ # f_start = (T * 365 - n * ad)
+ # t = [(x * ad) + f_start for x in range(n + 1)]
+ #
+ # # Price
+ # result = engine.price(T=t, ntrials=NTRIALS)
+ # s = '{0},{1:.6g},{2:.6g},{3:.6g},{4:.6g},{5:.6g},{6},{7},' \
+ # '{8:.6g}\n'.format(
+ # idx, S, K, r, T, vol, right, ad, result.price
+ # )
+ # f.write(s)
+ # idx += 1
+
+ # (iii) an Asian call option with maturity in T year(s) and
+ # 7 days averaging.
+ ad = 7
+ n = int(T * 365 // ad)
+ if n > 1:
+ # f_start = (T * 365 - n * ad)
+ # t = [(x * ad) + f_start for x in range(n + 1)]
+ t = [(x * ad / 365.) for x in range(n + 1)]
+
+ # Price
+ result = engine.price(T=t, ntrials=NTRIALS)
+ if abs(result.price) < 1E-5:
+ continue
+ s = '{0},{1:.6g},{2:.6g},{3:.6g},{4:.6g},{5:.6g},{6},{7},' \
+ '{8:.6g}\n'.format(
+ idx, S, K, r, T, vol, right, ad, result.price
+ )
+ f.write(s)
+ idx += 1
+ idy += 1
+
+
+def barrier() -> None:
+ """Generate barrier option fake data."""
+ outfile = './barrier.csv'
+
+ with open(outfile, 'w') as f:
+ s = 'ID,Spot,Strike,Risk-Free Rate,Years to Expiry,Volatility,' \
+ 'Option Right,Barrier Value,Barrier UpDown,Barrier InOut,Mesh Spacing,Price\n'
+ f.write(s)
+
+ idx = 0
+ for right in ('Call', 'Put'):
+ for b_inout in ('In', 'Out'):
+ for b_updown in ('Up', 'Down'):
+ idy = 0
+ while idy < NGEN:
+ B, S, K, T, r, vol = np.random.random(6)
+ B *= 300
+ S *= 300
+ K *= 300
+ r = r * 1E-2 - 5E-3
+ T *= 1
+ vol += 1E-4
+
+ path = PathGenerator(S=S, r=r, div=0., vol=vol)
+ payoff = DiscreteBarrierPayOff(
+ K=K, option_right=right, B=B,
+ barrier_updown=b_updown, barrier_inout=b_inout
+ )
+ engine = PricingEngine(payoff=payoff, path=path)
+
+ # (i) Monthly barrier dates.
+ bd = 30
+ n = int(T * 365 // bd)
+ if n > 1:
+ t = [(x * bd / 365.) for x in range(n + 1)]
+
+ # Price
+ result = engine.price(T=t, ntrials=NTRIALS)
+ if abs(result.price) < 1E-5:
+ continue
+ s = '{0},{1:.6g},{2:.6g},{3:.6g},{4:.6g},{5:.6g},{6},{7:.6g},{8},' \
+ '{9},{10},{11:.6g}\n'.format(
+ idx, S, K, r, T, vol, right, B, b_updown,
+ b_inout, bd, result.price
+ )
+ f.write(s)
+ idx += 1
+ idy += 1
+
+ # (i) Weekly barrier dates.
+ bd = 7
+ n = int(T * 365 // bd)
+ if n > 1:
+ t = [(x * bd / 365.) for x in range(n + 1)]
+
+ # Price
+ result = engine.price(T=t, ntrials=NTRIALS)
+ if abs(result.price) < 1E-5:
+ continue
+ s = '{0},{1:.6g},{2:.6g},{3:.6g},{4:.6g},{5:.6g},{6},{7:.6g},{8},' \
+ '{9},{10},{11:.6g}\n'.format(
+ idx, S, K, r, T, vol, right, B, b_updown,
+ b_inout, bd, result.price
+ )
+ f.write(s)
+ idx += 1
+ idy += 1
+
+
+def main() -> None:
+ random.seed(1)
+
+ # Pricing Vanilla options
+ # vanilla()
+
+ # Pricing Asian options
+ asian()
+
+ # Pricing discrete barrier options
+ # barrier()
+
+ print('==================')
+ print('Shivesh Mandalia https://shivesh.org/')
+ print('==================')
+
+
+main.__doc__ = __doc__
+
+
+if __name__ == '__main__':
+ main()