Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import wst.core.gromit as gromit
- from wst.ui.application import SimpleApp, SimpleAppView, SimpleAppController
- from wst.ui.controls import Button, Label, NumericField, TextField
- from wst.ui.layout import Col, Row
- import datetime
- from wst.ts.tsfns import ts_object
- from wst.lib.tenor import ContractTenor
- from wst.core.analytics import bs
- # We follow the MVC pattern to define a complete application in python. The platform has a special
- # dependency graph framework that we use to make applications reactive without too much code. If
- # you run this app and see what it does first, then look at how its constructed. You should be able
- # to get a reasonably functional web app without writing and javascript/css/html, however if you
- # web dev skills you can certainly make the app nicer if you like.
- class Model(gromit.Object):
- '''Model class for the calculator.
- Implement the model (back end) of the application. The model has two inputs fields with a
- special decorator and and output field which the same decorator with different settings.
- You can see from playing with the app that when you type into the inputs the Sum function
- runs and the new value gets pushed into the view. This is magically happening in part due
- to the decorators below. Understanding these graph is an advanced topic, for now its
- sufficient to note that something interesting is happening which can be used to create
- reactive behavior, but there are some caveats.
- '''
- @gromit.fn(gromit.Stored)
- def Input1(self):
- return 'Energy/CMECLopts'
- @gromit.fn(gromit.Stored)
- def Input2(self):
- return 2
- @gromit.fn
- def Sum(self):
- return self.Input1() + self.Input2()
- def getVolitility(self,call,strike_price,price,exp,today):
- print(call)
- print(strike_price)
- print(price)
- is_call = call
- spot = int(price * 100)
- strike = int(strike_price * 100)
- exp_date = datetime.date(2018, 7, 31)
- today = datetime.date(2018, 2, 20)
- texp = texp = (exp_date - today).days / 365.
- print(spot)
- print(strike)
- vol = bs.imp_vol(
- is_call,
- spot,
- strike,
- texp,
- 0,
- 0,
- 697
- )
- print('Volatility:', vol)
- def calcStockStuff(self):
- market_object = gromit.ns['/Assets/Energy/CME CL']
- # Lets try and get the prices for this future. If you were to click on 'Settlements' from the web page
- # you will see a table which the contract months that are available and the settlement prices in the
- # column 'Settle'. You can move the date dropdown to go back time.
- # The prices are stored in a time series, which is an ordered dictionary of date, curve pairs.
- # We can select a day's price (if the data is there) using some handy function calls.
- market_date = datetime.date(2018, 2, 21)
- price_ts = ts_object(gromit.ns, 'Energy/CMECLfuts')
- price_curve = price_ts.Value(market_date)
- print('Prices:', price_curve)
- #Note that only valid days in the past will work when asking for data. The data you see shoud
- #match what you see on the Nymex website. So now you have the underlying prices for a market.
- #To get to the option prices you'll need a companion time series
- # Energy/CMECLopts
- opt_ts = ts_object(gromit.ns, self.Input1())
- option_curve = opt_ts.Value(market_date)
- print('Option prices:', option_curve)
- # The format of the option data is (is_call, strike, option price). Recall that given these things
- #plus some additional information and our BS function we can turn this information into a volatility
- # Aside from printing these python objects, what other functionality do they have? After executing
- # this script it puts the local variables into the IPython shell. You can ask the objects for
- # their type (ex. type(market_objet)). That should print out the module name which will be in a folder
- # /wst/mktint/nrgfut.py (see the left tree)
- # In that module (and base classes) will be a lot of useful functionality. One thing that we need to
- # find is when do options expire. Handily
- exp_code = ContractTenor('Dec18')
- exp_date = market_object.ExpirationDate(exp_code)
- print('Expiration:', exp_date)
- print(type(option_curve))
- method_list = [func for func in dir(option_curve) if callable(getattr(option_curve, func))]
- print(method_list)
- print(option_curve.values())
- values = option_curve.values()
- dates = option_curve.tenors()
- print(type(values))
- print(option_curve.tenors())
- # print("test")
- for index,i in enumerate(values):
- for x in i:
- print(dates[index])
- self.getVolitility(x[0],float(x[1]),float(x[2]),exp_date,datetime.datetime.strptime(str(dates[index]),'%b%d').date())
- class AppController(SimpleAppController):
- '''
- The controller is the part of the mvc framework that connects the model and the view. This where you would put things like
- action to operate when buttons are clicked.
- '''
- def __init__(self, model):
- self.model = model
- def double1(self):
- '''
- This method when called modified a value on the model. Note that the value was in fact a method on the model which
- returns a constant. That method is actually a special object that caches a state variable with a default. The default
- value is what the method returns (1 or 2), but you can change the cached value by calling a function that is accessed through
- the function that you can call as below. That modification to an input of another function (Sum) will automatically trigger
- Beacon to know that anybody who is looking at the Sum of that model needs to get a new value.
- '''
- self.model.Input1.set_value(self.model.Input1() * 2)
- def getStockStuff(self):
- print("ran")
- stock_stuff = self.model.calcStockStuff()
- return stock_stuff
- #
- # 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.
- #
- # There is a main wiki page for UI in general (https://wst.wsq.io/wst/wiki/training/gromit-simple)
- #
- # But I suggest you concentrate on the the bits that are crucial:
- #
- # What are all the widgets and how do I lay them out (the bits under Components overview)
- # And even better sume examples
- #
- # wst/ui/examples/* (not everything in there will run, so ignore what does not)
- #
- # But let me draw your attention to:
- #
- # wst/ui/examples/app_controls.py - best way to see what you have in your tool bag (see 06 to fully digest the code)
- # wst/ui/examples/app_chart_* -
- # wst/ui/examples/app_spreadsheet_*
- #
- # Please ignore anything that has to do with 'glint' which is an under-development next version of ui UI plantform
- #
- def create_views(controller):
- '''Returns a list of views - in this case, just one view'''
- # construct the view, so we have a list of components organized into rows
- view_content = [
- # The first row has 3 components sized relatively based on the size weights. THe importand detail here
- # is binding to controller.model.Input1 which is how the form field in the browser will know to
- # be in sync with the field on the model. Also not how to apply a callback to the button click
- # through the controller.
- Row([
- Col(size=3, content=Label('Stock Price:')),
- Col(size=3, content=TextField(controller.model.Input1)),
- Col(size=6, content=Button('Calculate', on_click=controller.getStockStuff)),
- ]),
- ]
- # Finally all the components are put into a view which is assigned a controller
- view = SimpleAppView(content=view_content, controller=controller, view_name='index')
- return [view]
- def main():
- # Here is where the model, controller and view are instantiated and then they launch an async web page
- model = gromit.ns.new(Model)
- controller = AppController(model)
- app_views = create_views(controller)
- app = SimpleApp(
- views=app_views,
- title="Simple Calculator"
- )
- app.run()
- return controller
- if __name__ == '__main__':
- # While the app is running you can still use the IPython shell. With a reference to the controller you can
- # do things like inspecting your model to make sure it's doing what you want
- # ex. controller.model.Sum() should show you the same number on screen
- # and if you were to do something like call
- # controler.model.Input1.set_value(20) you should see you UI updates
- #
- controller = main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement