Package: dalio
The Dal.io DocumentationTable of ContentsIntroductionInstalationA Guided ExampleNext StepsIntroductionDal-io is a financial modeling package for python aiming to facilitate the gathering, wrangling and analysis of financial data. The library usesgraphical object structuresandprogressive display of complexityto make workflows suit the user's specific proficiency in python whithout making efficiency
sacrifices.The core library implements common workflows from well-supported packages and the means to flexibly interlink them, and aims to continue adding relevent features. However, the user is not constrained by these features, and is free to extend pieces through inheritance in order to implement extra functionality that can be used with the rest of the package. Seedevelopers_guidefor more information on extending core features.InstalationYou can clone this repository from git usinggitclonehttps://github.com/renatomatz/Dal-ioIf you are using Windows, make sure you are in the package folder to use the functionality and that you run the following command before importing the modules.importsyssys.path.append("/path-to-dalio/Dal-io")For Linux and Mac, you can access the package contents from your python environment anywhere withexportPYTHONPATH=$PYTHONPATH:"path/to/Dal-io"A Guided ExampleLet's go through a quick example of what Dal-io can do. We'll build a simple portfolio optimization workflow and test it out with some sample stocks.This example will be fairly dry, so if you want to jump right into it with some understanding of the Dal-io mechanics, you can go through thebeginners_guidefirst. If you just want to see what the library is capable of, let's get right to it.We'll start off by importing the Dal-io piecesimportnumpyasnpimportdalio.externalasdeimportdalio.translatorasdtimportdalio.pipeasdpimportdalio.modelasdmimportdalio.applicationasdaSpecific pieces can also be imported inidvidually, though for testing this sub-module import structure is preferred.Now lets set up our stock data input from Yahoo! Finance.tickers=["GOOG","MSFT","ATVI","TTWO","GM","FORD","SPY"]stocks=dt.YahooStockTranslator()\.set_input(de.YahooDR())Easy right? Notice that the stock input is composed of one external source (in this casede.YahooDR) and one translator (dt.YahooStockTranslator). This is the case for any input, with one piece getting raw data from an external source and another one translating it to a format friendly to Dal-io pieces. For more on formatting, go toformatting.Notice the.set_inputcall that took in the YahooDR object. Every all translators, pipes, models and applications share this method that allows them to plug the ourput of another object as their own input. This idea of connecting different objects like nodes in a graph is at the core of thegraphical object design.At this point you can try out running the model with :code:stocks.run(ticker=tickers)which will get the OHLCV data for the ticker symbols assigned to :code"tickers, though you can specify any ticker available in Yahoo! finance. Notice that the column names where standardized to be all lower-case with undercores (_) instead of spaces. This is performed as part of the translation step to ensure all imported data can be referenced with common string representations.Now lets create a data processing pipeline for our input data.time_conf=dp.DateSelect()close=dp.PipeLine(dp.ColSelect(columns="close"),time_conf)(stocks)annual_rets=close+\dp.Period("Y",agg_func=lambdax:x[-1])+\dp.Change(strategy="pct_change")cov=dp.Custom(lambdadf:df.cov(),strategy="pipe")\.with_input(annual_rets)exp_rets=annual_rets+dp.Custom(np.mean)That was a bit more challenging! Let's take it step by step.We started off defining a DateSelect pipe (which we will use later) and passingit into a pipeline with other pipes to get a company's annual returns. Pipelines aggregate zero or more Pipe objects and pass in a common input through all of their transformations. This skips data integrity checking while still allowing users to control pipes inside the pipeline from the outside (as we will withtime_conf)We then passed added a custom pipe that applies the np.mean function to the annualr returns to get the expected returns for each stock.Finally, we did the exact same thing but with a lambda that calls the pd.DataFrame internal method .cov() to get the dataframe's covariance. As we will be passing the whole dataframe to the function at once, we set the Custom strategy to "pipe".Notice how we didn't use.set_input()as we did before, that's because we utilized alternative ways of establishing this same node-to-node connection.We can connect nodes with:p1.set_input(p2)set p1's input to p2.p1.with_input(p2)create a copy of p1 and set its input to p2.p1(p2)same asp1.with_input(p2).pL + p2set p2 as the last transformation in the PipeLine pL.Now let's set up our efficient frontier model, get the optimal weights and finally create our optimal portfolio model.ef=dm.MakeEfficientFrontier(weight_bounds=(-0.5,1))\.set_input("sample_covariance",cov)\.set_input("expected_returns",exp_rets)\weights=dp.OptimumWeights()(ef)\.set_piece("strategy","max_sharpe",risk_free_rate=0.0)opt_port=dm.OptimumPortfolio()\.set_input("weights_in",weights)\.set_input("data_in",close)And those are two examples of Dal-io Models! As you can see, models can have multiple named inputs, which can be set the same way as you would in a pipe but also having to specify their name. You also saw an example of a Builder, which has pieces (that can be set with the.set_piece()) method which allow for more modular flexibility when deciding characteristics of certain pipes or models.We could go into what each source and pieces represents, but that can be better done through the documentation.Now, as a final step, lets graph the performance of the optimal portfolio.graph=da.PandasXYGrapher(x=None,y="close",legend="upper_right")\.set_input("data_in",dp.Index(100)(opt_port))\.set_output("data_out",de.PyPlotGraph(figsize=(12,8)))Additionally, you can change the time range of the whole model at any point using thetime_confobject we created all the way in the beginning. Below is an example of setting the dates from 2016 to 2020.time_conf.set_start("2016-01-01")time_conf.set_end("2019-12-31")And that's it!All that you have to do now is run the model with :code:graph.run(ticker=tickers)toGet stock data from Yahoo! FinanceProcess dataOptimize portfolio weightsGet an optimum portfolioGraph optimum portfolioWhich yields this figure:Notice how this :code:.run()call was the same as you did all the way back when you only had your imported data. This method is also common to all translators, pipes, models and applications, and it gives you the piece's output.This means you can get information of any of the stages you created like this, and for anly stock that you'd like. For example, we can run the :code:weightsobject we created to get the weights associated with the portfolio we just plotted.weights.run(ticker=tickers){'GOOG':0.45514,'MSFT':0.82602,'ATVI':-0.49995,'TTWO':0.29241,'GM':-0.43788,'FORD':0.38413,'SPY':-0.01986}Hope this example was enough to show how you can create clean and powerful models using just a few lines of code!Next StepsIf you read and enjoyed the example above, that's great! Now comes the part where you get to understand its various pieces, workflows and internal logic for you to start creating your own models with Dal-io.Check out our documentation atthe Dal-io Documentation