Quansight / omnisci

Explorations on using MapD and Jupyter together.
4 stars 1 forks source link

Black-Scholes model computations #138

Closed pearu closed 3 years ago

pearu commented 3 years ago

The Black–Scholes formula calculates the price of European put and call options.

The example of the BS formula application can be formulated both as a UDF as well as UDTF.

Goal: show a simple self-contained compute example that uses numpy functions under the hood

References:

Notes:

Tasks:

Here is an initial implementation of BS as a UDF:

``` table_name = os.path.splitext(os.path.basename(__file__))[0] @pytest.fixture(scope='module') def omnisci(): config = rbc_omnisci.get_client_config(debug=not True) omnisci = rbc_omnisci.RemoteOmnisci(**config) omnisci.sql_execute(f'DROP TABLE IF EXISTS {table_name}') omnisci.sql_execute(f'CREATE TABLE IF NOT EXISTS {table_name} (S DOUBLE);') for i in range(10): S = 10 + (random.random() - 0.5) * 5 omnisci.sql_execute(f'INSERT INTO {table_name} VALUES ({S})') yield omnisci omnisci.sql_execute(f'DROP TABLE IF EXISTS {table_name}') def test_blackscholes_udf(omnisci): @numba.njit def cnd(d): # element-wise cnd A1 = 0.31938153 A2 = -0.356563782 A3 = 1.781477937 A4 = -1.821255978 A5 = 1.330274429 RSQRT2PI = 0.39894228040143267793994605993438 K = 1.0 / (1.0 + 0.2316419 * np.abs(d)) ret_val = (RSQRT2PI * np.exp(-0.5 * d * d) * (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5)))))) if d > 0: return 1.0 - ret_val return ret_val signature = 'double(double, double, double, double, double, bool)' def blackscholes(stockPrice, optionStrike, optionYears, Riskfree, Volatility, getcall): S = stockPrice X = optionStrike T = optionYears R = Riskfree V = Volatility sqrtT = np.sqrt(T) d1 = (np.log(S / X) + (R + 0.5 * V * V) * T) / (V * sqrtT) d2 = d1 - V * sqrtT cndd1 = cnd(d1) cndd2 = cnd(d2) expRT = np.exp(- R * T) if getcall: callResult = S * cndd1 - X * expRT * cndd2 return callResult else: putResult = X * expRT * (1.0 - cndd2) - S * (1.0 - cndd1) return putResult omnisci(signature)(blackscholes) X = 10 T = 5 R = 0.1 V = 0.2 # Compute test output in the server descr, result = omnisci.sql_execute( f'''select S, blackscholes(S, CAST({X} as DOUBLE), CAST({T} as DOUBLE), CAST({R} as DOUBLE), CAST({V} as DOUBLE), TRUE), blackscholes(S, CAST({X} as DOUBLE), CAST({T} as DOUBLE), CAST({R} as DOUBLE), CAST({V} as DOUBLE), FALSE) from {table_name};''' ) for S, C, P in result: print(S, C, P) ```
guilhermeleobas commented 3 years ago

For future reference, I am using data from this website rather than live data from Yahoo Finance!. One of the columns from this site contains the approximated value for the black-scholes model.

guilhermeleobas commented 3 years ago

Pull Request has been submitted with implementing both the UDF and UDTF black-scholes model. https://github.com/xnd-project/rbc/pull/166

pearu commented 3 years ago

https://github.com/xnd-project/rbc/blob/master/notebooks/black_scholes_UDF.ipynb