Guest User

Untitled

a guest
Feb 25th, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.39 KB | None | 0 0
  1. from functools import partial
  2. import wst.core.gromit as gromit
  3. from wst.ui.application import SimpleApp, SimpleAppView, SimpleAppController
  4. from wst.ui.controls import Button, Label, TextField, IFrame
  5. from wst.ui.layout import Col, Row, VList
  6. import datetime
  7. from wst.ts.tsfns import ts_object
  8. from wst.lib.tenor import ContractTenor
  9. from wst.core.analytics import bs
  10. import scipy.stats
  11. import numpy
  12. import math
  13. from mpl_toolkits.mplot3d import axes3d
  14. import matplotlib.pyplot as plt
  15. from matplotlib import cm
  16. # Shit Code, BSM returns zero. Shall check later
  17.  
  18. # We follow the MVC pattern to define a complete application in python. The platform has a special
  19. # dependency graph framework that we use to make applications reactive without too much code. If
  20. # you run this app and see what it does first, then look at how its constructed. You should be able
  21. # to get a reasonably functional web app without writing and javascript/css/html, however if you
  22. # web dev skills you can certainly make the app nicer if you like.
  23.  
  24. def show_view(model, name):
  25. model.target_url.set_value(name)
  26.  
  27. class ViewModel(gromit.Object):
  28. @gromit.fn(gromit.CanSet)
  29. def target_url(self):
  30. return "./#/stock"
  31.  
  32. class Model(gromit.Object):
  33. '''Model class for the calculator.
  34.  
  35. Implement the model (back end) of the application. The model has two inputs fields with a
  36. special decorator and and output field which the same decorator with different settings.
  37.  
  38. You can see from playing with the app that when you type into the inputs the Sum function
  39. runs and the new value gets pushed into the view. This is magically happening in part due
  40. to the decorators below. Understanding these graph is an advanced topic, for now its
  41. sufficient to note that something interesting is happening which can be used to create
  42. reactive behavior, but there are some caveats.
  43. '''
  44. volatilities = []
  45. prices = []
  46.  
  47. @gromit.fn(gromit.Stored)
  48. def Input1(self):
  49. return 'Energy/CMECLopts'
  50.  
  51. def getVolitility(self,call,strike_price,price,exp,today):
  52.  
  53. print(call)
  54. print(strike_price)
  55. print(price)
  56.  
  57. is_call = call
  58.  
  59. spot = int(price * 100)
  60. strike = int(strike_price * 100)
  61. # exp_date = datetime.date(2018, 7, 31)
  62. today = datetime.date(2018, 2, 20)
  63. texp = texp = (exp - today).days / 365.
  64.  
  65. print(spot)
  66. print(strike)
  67.  
  68. try:
  69. vol = bs.imp_vol(
  70. is_call,
  71. spot,
  72. strike,
  73. texp,
  74. 0,
  75. 0,
  76. 697
  77. )
  78. except:
  79. return False
  80.  
  81. print('Volatility:', vol)
  82. def checkCallPrice(self,price, mean, std, strike_price, exp):
  83. today = datetime.date(2018, 2, 20)
  84. dtm = (exp - today).days / 365.
  85. d = (numpy.log(price / strike_price) + ((0.03 + std/2) * dtm)) / (std*numpy.sqrt(dtm))
  86. d_two = (numpy.log(price / strike_price) + ((0.03 - std/2) * dtm)) / (std*numpy.sqrt(dtm))
  87. bsm = price * (scipy.stats.norm(mean, std).pdf(d)) - (price * math.exp(-0.03*dtm) * scipy.stats.norm(mean,std).pdf(d_two))
  88. print(bsm)
  89.  
  90. def checkPutPrice(self, price, mean, std, strike_price, exp):
  91. today = datetime.date(2018, 2, 20)
  92. dtm = (exp - today).days / 365.
  93. d = (numpy.log(price / strike_price) + ((0.03 + std/2) * dtm)) / (std*numpy.sqrt(dtm))
  94. d_two = (numpy.log(price / strike_price) + ((0.03 - std/2) * dtm)) / (std*numpy.sqrt(dtm))
  95. bsm = (price * math.exp(-0.03*dtm)* scipy.stats.norm(mean,std).pdf(d_two * -1)) - price * (scipy.stats.norm(mean, std).pdf(d * -1))
  96. print(bsm)
  97.  
  98. def calcStockStuff(self):
  99. market_object = gromit.ns['/Assets/Energy/CME CL']
  100.  
  101. # Lets try and get the prices for this future. If you were to click on 'Settlements' from the web page
  102. # you will see a table which the contract months that are available and the settlement prices in the
  103. # column 'Settle'. You can move the date dropdown to go back time.
  104.  
  105. # The prices are stored in a time series, which is an ordered dictionary of date, curve pairs.
  106. # We can select a day's price (if the data is there) using some handy function calls.
  107.  
  108. market_date = datetime.date(2018, 2, 21)
  109. price_ts = ts_object(gromit.ns, 'Energy/CMECLfuts')
  110. price_curve = price_ts.Value(market_date)
  111.  
  112. print('Prices:', price_curve)
  113.  
  114. #Note that only valid days in the past will work when asking for data. The data you see shoud
  115. #match what you see on the Nymex website. So now you have the underlying prices for a market.
  116. #To get to the option prices you'll need a companion time series
  117. # Energy/CMECLopts
  118.  
  119. opt_ts = ts_object(gromit.ns, self.Input1())
  120. option_curve = opt_ts.Value(market_date)
  121.  
  122. print('Option prices:', option_curve)
  123.  
  124. # The format of the option data is (is_call, strike, option price). Recall that given these things
  125. #plus some additional information and our BS function we can turn this information into a volatility
  126.  
  127. # Aside from printing these python objects, what other functionality do they have? After executing
  128. # this script it puts the local variables into the IPython shell. You can ask the objects for
  129. # their type (ex. type(market_objet)). That should print out the module name which will be in a folder
  130. # /wst/mktint/nrgfut.py (see the left tree)
  131.  
  132. # In that module (and base classes) will be a lot of useful functionality. One thing that we need to
  133. # find is when do options expire. Handily
  134.  
  135. exp_code = ContractTenor('Dec18')
  136. exp_date = market_object.ExpirationDate(exp_code)
  137.  
  138. print('Expiration:', exp_date)
  139.  
  140. print(type(option_curve))
  141. method_list = [func for func in dir(option_curve) if callable(getattr(option_curve, func))]
  142. print(method_list)
  143. print(option_curve.values())
  144.  
  145. # shit code is shit code
  146.  
  147. values = option_curve.values()
  148. dates = option_curve.tenors()
  149. prices = price_curve.values()
  150. strike_prices = []
  151. new_dates = []
  152. for index,i in enumerate(values):
  153. for x in i:
  154. volitility = self.getVolitility(x[0],float(x[1]),float(x[2]),datetime.datetime.strptime(str(dates[index]),'%b%y').date(),'test')
  155. if(volitility) != False:
  156. self.volatilities.append(volitility)
  157. self.prices.append(prices[index])
  158. strike_prices.append(x[1])
  159. new_dates.append(datetime.datetime.strptime(str(dates[index]),'%b%y').date())
  160.  
  161. mean = sum(self.prices)
  162. std = numpy.std(self.prices)
  163. print('here')
  164. for index,volitility in enumerate(self.volatilities):
  165. if volitility != False:
  166. if x[0]:
  167. self.checkCallPrice(self.prices[index], mean, std, strike_prices[index], new_dates[index])
  168. else:
  169. self.checkPutPrice(self.prices[index], mean, std, strike_prices[index], new_dates[index])
  170.  
  171. class AppController(SimpleAppController):
  172. '''
  173. The controller is the part of the mvc framework that connects the model and the view. This where you would put things like
  174. action to operate when buttons are clicked.
  175.  
  176. '''
  177.  
  178. def __init__(self, model):
  179. self.model = model
  180.  
  181.  
  182. def getStockStuff(self):
  183. print("ran")
  184. stock_stuff = self.model.calcStockStuff()
  185. return stock_stuff
  186.  
  187.  
  188. #
  189. # The last part of the puzzle is the view. This is simply a representation of the view where the layout id described in python objects.
  190. #
  191. # There is a main wiki page for UI in general (https://wst.wsq.io/wst/wiki/training/gromit-simple)
  192. #
  193. # But I suggest you concentrate on the the bits that are crucial:
  194. #
  195. # What are all the widgets and how do I lay them out (the bits under Components overview)
  196. # And even better sume examples
  197. #
  198. # wst/ui/examples/* (not everything in there will run, so ignore what does not)
  199. #
  200. # But let me draw your attention to:
  201. #
  202. # wst/ui/examples/app_controls.py - best way to see what you have in your tool bag (see 06 to fully digest the code)
  203. # wst/ui/examples/app_chart_* -
  204. # wst/ui/examples/app_spreadsheet_*
  205. #
  206. # Please ignore anything that has to do with 'glint' which is an under-development next version of ui UI plantform
  207. #
  208.  
  209. def volatility_plot():
  210.  
  211. #We use matplotlib to to generate a chart. This is a popular python package.
  212. min = min(model.
  213. fig = plt.figure()
  214. ax = fig.gca(projection='3d')
  215. X, Y, Z = axes3d.get_test_data(0.05)
  216. ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
  217. cset = ax.contour(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm)
  218. cset = ax.contour(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm)
  219. cset = ax.contour(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm)
  220.  
  221. ax.set_xlabel('X')
  222. ax.set_xlim(-40, 40)
  223. ax.set_ylabel('Y')
  224. ax.set_ylim(-40, 40)
  225. ax.set_zlabel('Z')
  226. ax.set_zlim(-100, 100)
  227.  
  228. #Unfortunately you can't see it in your browser, the package shows the image on the remote machine
  229. #in amazon
  230. plt.show()
  231.  
  232. #But we can create a temporary image and embed it directly into an html page
  233. plt.savefig('temp.png')
  234. import base64
  235. data_uri = base64.b64encode(open('temp.png', 'rb').read()).decode('utf-8').replace('\n','')
  236. img_tag = '<img src="data:image/png;base64,{0}">'.format(data_uri)
  237. html = '<html>Volatility<b>%sFooter<b></html>' % img_tag
  238.  
  239. return html
  240.  
  241. def pl_plot():
  242.  
  243. #We use matplotlib to to generate a chart. This is a popular python package.
  244.  
  245. fig = plt.figure()
  246. ax = fig.gca(projection='3d')
  247. X, Y, Z = axes3d.get_test_data(0.05)
  248. ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
  249. cset = ax.contour(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm)
  250. cset = ax.contour(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm)
  251. cset = ax.contour(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm)
  252.  
  253. ax.set_xlabel('X')
  254. ax.set_xlim(-40, 40)
  255. ax.set_ylabel('Y')
  256. ax.set_ylim(-40, 40)
  257. ax.set_zlabel('Z')
  258. ax.set_zlim(-100, 100)
  259.  
  260. #Unfortunately you can't see it in your browser, the package shows the image on the remote machine
  261. #in amazon
  262. plt.show()
  263.  
  264. #But we can create a temporary image and embed it directly into an html page
  265. plt.savefig('temp.png')
  266. import base64
  267. data_uri = base64.b64encode(open('temp.png', 'rb').read()).decode('utf-8').replace('\n','')
  268. img_tag = '<img src="data:image/png;base64,{0}">'.format(data_uri)
  269. html = '<html>P&L<b>%sFooter<b></html>' % img_tag
  270.  
  271. return html
  272.  
  273. def greeks_plot():
  274.  
  275. #We use matplotlib to to generate a chart. This is a popular python package.
  276.  
  277. fig = plt.figure()
  278. ax = fig.gca(projection='3d')
  279. X, Y, Z = axes3d.get_test_data(0.05)
  280. ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
  281. cset = ax.contour(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm)
  282. cset = ax.contour(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm)
  283. cset = ax.contour(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm)
  284.  
  285. ax.set_xlabel('X')
  286. ax.set_xlim(-40, 40)
  287. ax.set_ylabel('Y')
  288. ax.set_ylim(-40, 40)
  289. ax.set_zlabel('Z')
  290. ax.set_zlim(-100, 100)
  291.  
  292. #Unfortunately you can't see it in your browser, the package shows the image on the remote machine
  293. #in amazon
  294. plt.show()
  295.  
  296. #But we can create a temporary image and embed it directly into an html page
  297. plt.savefig('temp.png')
  298. import base64
  299. data_uri = base64.b64encode(open('temp.png', 'rb').read()).decode('utf-8').replace('\n','')
  300. img_tag = '<img src="data:image/png;base64,{0}">'.format(data_uri)
  301. html = '<html>Greeks<b>%sFooter<b></html>' % img_tag
  302.  
  303. return html
  304.  
  305. class MainView(SimpleAppView):
  306. def __init__(self, model):
  307. content = VList([
  308. '<h2>Volatility, P&L, and the Greeks</h2>',
  309. Button('Stock', on_click=partial(show_view, model, './#/stock')),
  310. Button('Volatility', on_click=partial(show_view, model, './#/volatility')),
  311. Button('P&L', on_click=partial(show_view, model, './#/pl')),
  312. Button('Greeks', on_click=partial(show_view, model, './#/greeks')),
  313.  
  314. #We can embed html content directly into an IFrame
  315. IFrame(src=model.target_url, css_style="height: 800px;max-width:100vw;"),
  316. volatility_view
  317. ])
  318. super().__init__(content, view_name="index")
  319.  
  320. class StockView(SimpleAppView):
  321. def __init__(self,model,inner_model,controller):
  322. content = [
  323. Row([
  324. Col(size=3, content=Label('Stock Price:')),
  325. Col(size=3, content=TextField(inner_model.Input1)),
  326. Col(size=6, content=Button('Calculate', on_click=controller.getStockStuff)),
  327. ]),
  328. ]
  329. super().__init__(content, view_name="stock")
  330.  
  331.  
  332.  
  333. def volatility_view():
  334. html = volatility_plot()
  335.  
  336. return html
  337.  
  338. def pl_view():
  339. html = pl_plot()
  340.  
  341. return html
  342.  
  343. def greeks_view():
  344. html = greeks_plot()
  345.  
  346. return html
  347.  
  348. class VolatilityView(SimpleAppView):
  349. def __init__(self,model,inner_model,controller):
  350. content = [
  351. volatility_view()
  352. ]
  353. super().__init__(content, view_name='volatility')
  354.  
  355. class PLView(SimpleAppView):
  356. def __init__(self,model,inner_model,controller):
  357. content = [
  358. pl_view()
  359. ]
  360. super().__init__(content, view_name='pl')
  361.  
  362.  
  363. class GreeksView(SimpleAppView):
  364. def __init__(self,model,inner_model,controller):
  365. content = [
  366. greeks_view()
  367. ]
  368. super().__init__(content, view_name='greeks')
  369.  
  370.  
  371.  
  372. def main():
  373.  
  374. # Here is where the model, controller and view are instantiated and then they launch an async web page
  375.  
  376. model = ViewModel()
  377. inner_model = gromit.ns.new(Model)
  378.  
  379. controller = AppController(inner_model)
  380. #app_views = create_views(controller)
  381.  
  382. app = SimpleApp(views=[
  383. MainView(model),
  384. StockView(model,inner_model,controller),
  385. VolatilityView(model,inner_model,controller),
  386. PLView(model,inner_model,controller),
  387. GreeksView(model,inner_model,controller)
  388. ],
  389. title="Volitiliy Calculator",
  390. app_style="fluid-nohome-nofooter",
  391. show_db=False
  392. )
  393. app.run()
  394.  
  395. return controller
  396.  
  397.  
  398. if __name__ == '__main__':
  399.  
  400. # While the app is running you can still use the IPython shell. With a reference to the controller you can
  401. # do things like inspecting your model to make sure it's doing what you want
  402.  
  403. # ex. controller.model.Sum() should show you the same number on screen
  404. # and if you were to do something like call
  405. # controler.model.Input1.set_value(20) you should see you UI updates
  406. #
  407.  
  408. controller = main()
Add Comment
Please, Sign In to add comment