Advertisement
Guest User

Untitled

a guest
Feb 24th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.18 KB | None | 0 0
  1. import wst.core.gromit as gromit
  2. from wst.ui.application import SimpleApp, SimpleAppView, SimpleAppController
  3. from wst.ui.controls import Button, Label, NumericField, TextField
  4. from wst.ui.layout import Col, Row
  5. import datetime
  6. from wst.ts.tsfns import ts_object
  7. from wst.lib.tenor import ContractTenor
  8. from wst.core.analytics import bs
  9.  
  10. # We follow the MVC pattern to define a complete application in python. The platform has a special
  11. # dependency graph framework that we use to make applications reactive without too much code. If
  12. # you run this app and see what it does first, then look at how its constructed. You should be able
  13. # to get a reasonably functional web app without writing and javascript/css/html, however if you
  14. # web dev skills you can certainly make the app nicer if you like.
  15.  
  16. class Model(gromit.Object):
  17. '''Model class for the calculator.
  18.  
  19. Implement the model (back end) of the application. The model has two inputs fields with a
  20. special decorator and and output field which the same decorator with different settings.
  21.  
  22. You can see from playing with the app that when you type into the inputs the Sum function
  23. runs and the new value gets pushed into the view. This is magically happening in part due
  24. to the decorators below. Understanding these graph is an advanced topic, for now its
  25. sufficient to note that something interesting is happening which can be used to create
  26. reactive behavior, but there are some caveats.
  27. '''
  28.  
  29.  
  30. @gromit.fn(gromit.Stored)
  31. def Input1(self):
  32. return 'Energy/CMECLopts'
  33.  
  34. @gromit.fn(gromit.Stored)
  35. def Input2(self):
  36. return 2
  37.  
  38. @gromit.fn
  39. def Sum(self):
  40. return self.Input1() + self.Input2()
  41.  
  42. def getVolitility(self,call,strike_price,price,exp,today):
  43.  
  44. print(call)
  45. print(strike_price)
  46. print(price)
  47.  
  48. is_call = call
  49.  
  50. spot = int(price * 100)
  51. strike = int(strike_price * 100)
  52. exp_date = datetime.date(2018, 7, 31)
  53. today = datetime.date(2018, 2, 20)
  54. texp = texp = (exp_date - today).days / 365.
  55.  
  56. print(spot)
  57. print(strike)
  58.  
  59. vol = bs.imp_vol(
  60. is_call,
  61. spot,
  62. strike,
  63. texp,
  64. 0,
  65. 0,
  66. 697
  67. )
  68.  
  69. print('Volatility:', vol)
  70.  
  71. def calcStockStuff(self):
  72. market_object = gromit.ns['/Assets/Energy/CME CL']
  73.  
  74. # Lets try and get the prices for this future. If you were to click on 'Settlements' from the web page
  75. # you will see a table which the contract months that are available and the settlement prices in the
  76. # column 'Settle'. You can move the date dropdown to go back time.
  77.  
  78. # The prices are stored in a time series, which is an ordered dictionary of date, curve pairs.
  79. # We can select a day's price (if the data is there) using some handy function calls.
  80.  
  81. market_date = datetime.date(2018, 2, 21)
  82. price_ts = ts_object(gromit.ns, 'Energy/CMECLfuts')
  83. price_curve = price_ts.Value(market_date)
  84.  
  85. print('Prices:', price_curve)
  86.  
  87. #Note that only valid days in the past will work when asking for data. The data you see shoud
  88. #match what you see on the Nymex website. So now you have the underlying prices for a market.
  89. #To get to the option prices you'll need a companion time series
  90. # Energy/CMECLopts
  91.  
  92. opt_ts = ts_object(gromit.ns, self.Input1())
  93. option_curve = opt_ts.Value(market_date)
  94.  
  95. print('Option prices:', option_curve)
  96.  
  97. # The format of the option data is (is_call, strike, option price). Recall that given these things
  98. #plus some additional information and our BS function we can turn this information into a volatility
  99.  
  100. # Aside from printing these python objects, what other functionality do they have? After executing
  101. # this script it puts the local variables into the IPython shell. You can ask the objects for
  102. # their type (ex. type(market_objet)). That should print out the module name which will be in a folder
  103. # /wst/mktint/nrgfut.py (see the left tree)
  104.  
  105. # In that module (and base classes) will be a lot of useful functionality. One thing that we need to
  106. # find is when do options expire. Handily
  107.  
  108. exp_code = ContractTenor('Dec18')
  109. exp_date = market_object.ExpirationDate(exp_code)
  110.  
  111. print('Expiration:', exp_date)
  112.  
  113. print(type(option_curve))
  114. method_list = [func for func in dir(option_curve) if callable(getattr(option_curve, func))]
  115. print(method_list)
  116. print(option_curve.values())
  117.  
  118. values = option_curve.values()
  119. dates = option_curve.tenors()
  120. print(type(values))
  121. print(option_curve.tenors())
  122. # print("test")
  123. for index,i in enumerate(values):
  124. for x in i:
  125. print(dates[index])
  126. self.getVolitility(x[0],float(x[1]),float(x[2]),exp_date,datetime.datetime.strptime(str(dates[index]),'%b%d').date())
  127.  
  128.  
  129. class AppController(SimpleAppController):
  130. '''
  131. The controller is the part of the mvc framework that connects the model and the view. This where you would put things like
  132. action to operate when buttons are clicked.
  133.  
  134. '''
  135.  
  136. def __init__(self, model):
  137. self.model = model
  138.  
  139. def double1(self):
  140. '''
  141. This method when called modified a value on the model. Note that the value was in fact a method on the model which
  142. returns a constant. That method is actually a special object that caches a state variable with a default. The default
  143. value is what the method returns (1 or 2), but you can change the cached value by calling a function that is accessed through
  144. the function that you can call as below. That modification to an input of another function (Sum) will automatically trigger
  145. Beacon to know that anybody who is looking at the Sum of that model needs to get a new value.
  146.  
  147. '''
  148. self.model.Input1.set_value(self.model.Input1() * 2)
  149.  
  150. def getStockStuff(self):
  151. print("ran")
  152. stock_stuff = self.model.calcStockStuff()
  153. return stock_stuff
  154.  
  155.  
  156. #
  157. # 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.
  158. #
  159. # There is a main wiki page for UI in general (https://wst.wsq.io/wst/wiki/training/gromit-simple)
  160. #
  161. # But I suggest you concentrate on the the bits that are crucial:
  162. #
  163. # What are all the widgets and how do I lay them out (the bits under Components overview)
  164. # And even better sume examples
  165. #
  166. # wst/ui/examples/* (not everything in there will run, so ignore what does not)
  167. #
  168. # But let me draw your attention to:
  169. #
  170. # wst/ui/examples/app_controls.py - best way to see what you have in your tool bag (see 06 to fully digest the code)
  171. # wst/ui/examples/app_chart_* -
  172. # wst/ui/examples/app_spreadsheet_*
  173. #
  174. # Please ignore anything that has to do with 'glint' which is an under-development next version of ui UI plantform
  175. #
  176.  
  177. def create_views(controller):
  178. '''Returns a list of views - in this case, just one view'''
  179.  
  180. # construct the view, so we have a list of components organized into rows
  181.  
  182. view_content = [
  183.  
  184. # The first row has 3 components sized relatively based on the size weights. THe importand detail here
  185. # is binding to controller.model.Input1 which is how the form field in the browser will know to
  186. # be in sync with the field on the model. Also not how to apply a callback to the button click
  187. # through the controller.
  188.  
  189. Row([
  190. Col(size=3, content=Label('Stock Price:')),
  191. Col(size=3, content=TextField(controller.model.Input1)),
  192. Col(size=6, content=Button('Calculate', on_click=controller.getStockStuff)),
  193. ]),
  194.  
  195.  
  196. ]
  197.  
  198. # Finally all the components are put into a view which is assigned a controller
  199.  
  200. view = SimpleAppView(content=view_content, controller=controller, view_name='index')
  201.  
  202. return [view]
  203.  
  204.  
  205. def main():
  206.  
  207. # Here is where the model, controller and view are instantiated and then they launch an async web page
  208.  
  209. model = gromit.ns.new(Model)
  210. controller = AppController(model)
  211. app_views = create_views(controller)
  212.  
  213. app = SimpleApp(
  214. views=app_views,
  215. title="Simple Calculator"
  216. )
  217. app.run()
  218.  
  219. return controller
  220.  
  221.  
  222. if __name__ == '__main__':
  223.  
  224. # While the app is running you can still use the IPython shell. With a reference to the controller you can
  225. # do things like inspecting your model to make sure it's doing what you want
  226.  
  227. # ex. controller.model.Sum() should show you the same number on screen
  228. # and if you were to do something like call
  229. # controler.model.Input1.set_value(20) you should see you UI updates
  230. #
  231.  
  232. controller = main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement