import%20marimo%0A%0A__generated_with%20%3D%20%220.14.17%22%0Aapp%20%3D%20marimo.App()%0A%0Awith%20app.setup%3A%0A%20%20%20%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20plotly.io%20as%20pio%0A%20%20%20%20import%20polars%20as%20pl%0A%0A%20%20%20%20pd.options.plotting.backend%20%3D%20%22plotly%22%0A%0A%20%20%20%20%23%20Ensure%20Plotly%20works%20with%20Marimo%0A%20%20%20%20pio.renderers.default%20%3D%20%22plotly_mimetype%22%0A%0A%20%20%20%20path%20%3D%20Path(__file__).parent%20%2F%20%22public%22%20%2F%20%22stock-prices.csv%22%0A%0A%20%20%20%20%23%20from%20cvxsimulator.builder%20import%20polars2pandas%0A%20%20%20%20date_col%20%3D%20%22date%22%0A%20%20%20%20dframe%20%3D%20pl.read_csv(str(path)%2C%20try_parse_dates%3DTrue)%0A%0A%20%20%20%20dframe%20%3D%20dframe.with_columns(pl.col(date_col).cast(pl.Datetime(%22ns%22)))%0A%20%20%20%20dframe%20%3D%20dframe.with_columns(%5Bpl.col(col).cast(pl.Float64)%20for%20col%20in%20dframe.columns%20if%20col%20!%3D%20date_col%5D)%0A%20%20%20%20prices%20%3D%20dframe.to_pandas().set_index(date_col)%0A%0A%20%20%20%20from%20loguru%20import%20logger%0A%0A%20%20%20%20from%20cvxsimulator%20import%20Builder%0A%0A%20%20%20%20%23%20Initialize%20random%20number%20generator%20once%20to%20be%20used%20by%20all%20cells%0A%20%20%20%20rng%20%3D%20np.random.default_rng(42)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20%22%22%22Display%20the%20title%20of%20the%20notebook.%0A%0A%20%20%20%20Parameters%0A%20%20%20%20----------%0A%20%20%20%20mo%20%3A%20marimo.Module%0A%20%20%20%20%20%20%20%20The%20marimo%20module%20object%0A%0A%20%20%20%20%22%22%22%0A%20%20%20%20mo.md(r%22%22%22%23%20Almost%20pairs%20trading%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20This%20little%20exercise%20goes%20back%20to%20an%20idea%20by%20Stephen%20Boyd%3A%0A%0A%20%20%20%20The%20simulator%20should%20always%20be%20completely%20agnostic%20as%20to%20the%20trading%20policy.%0A%20%20%20%20You%20should%20even%20demonstrate%20this%20with%20silly%20policies.%0A%20%20%20%20Like%20here%E2%80%99s%20one%3A%20%20Each%20day%20choose%20names%20from%20the%20universe%20at%20random.%0A%20%20%20%20Buy%20one%20(say%200.1%20of%20your%20portfolio%20wealth)%20and%20short%20one%20the%20same%20amount.%0A%20%20%20%20Not%20a%20good%20strategy%2C%20but%20a%20valid%20one.%0A%20%20%20%20Of%20course%20the%20simulate%20will%20terminate%20if%20you%20go%20bust%20(which%20seems%20likely).%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20%22%22%22Implement%20the%20pairs%20trading%20strategy%20and%20build%20the%20portfolio.%0A%0A%20%20%20%20This%20cell%3A%0A%20%20%20%201.%20Loads%20price%20data%20from%20a%20CSV%20file%0A%20%20%20%202.%20Creates%20a%20Builder%20instance%20with%20the%20price%20data%20and%20initial%20AUM%0A%20%20%20%203.%20Implements%20the%20pairs%20trading%20strategy%3A%0A%20%20%20%20%20%20%20-%20For%20each%20time%20step%2C%20randomly%20selects%20two%20assets%0A%20%20%20%20%20%20%20-%20Goes%20long%20one%20asset%20and%20short%20the%20other%20with%20equal%20dollar%20amounts%0A%20%20%20%20%20%20%20-%20Allocates%2010%25%20of%20the%20portfolio%20to%20this%20pair%0A%20%20%20%204.%20Applies%20transaction%20costs%20(1%20bps%20of%20traded%20volume)%0A%20%20%20%205.%20Builds%20and%20returns%20the%20final%20portfolio%0A%0A%0A%20%20%20%20Returns%3A%0A%20%20%20%20-------%0A%20%20%20%20tuple%0A%20%20%20%20%20%20%20%20A%20tuple%20containing%20the%20built%20portfolio%0A%0A%20%20%20%20%22%22%22%0A%20%20%20%20logger.info(%22Load%20prices%22)%0A%20%20%20%20logger.info(%22Build%20portfolio%22)%0A%20%20%20%20b%20%3D%20Builder(prices%3Dprices%2C%20initial_aum%3D1e6)%0A%0A%20%20%20%20for%20_t%2C%20state%20in%20b%3A%0A%20%20%20%20%20%20%20%20assert%20state.nav%20%3E%200%2C%20%22Game%20over%22%0A%0A%20%20%20%20%20%20%20%20%23%20pick%20two%20assets%20at%20random%0A%20%20%20%20%20%20%20%20pair%20%3D%20rng.choice(state.assets%2C%202%2C%20replace%3DFalse)%0A%0A%20%20%20%20%20%20%20%20%23%20compute%20the%20pair%0A%20%20%20%20%20%20%20%20units%20%3D%20pd.Series(index%3Dstate.assets%2C%20data%3D0.0)%0A%20%20%20%20%20%20%20%20units%5Bpair%5D%20%3D%20%5Bstate.nav%2C%20-state.nav%5D%20%2F%20state.prices%5Bpair%5D.to_numpy()%0A%20%20%20%20%20%20%20%20b.position%20%3D%200.1%20*%20units%0A%0A%20%20%20%20%20%20%20%20%23%201%20bps%20of%20the%20traded%20volume%20(measured%20in%20USD)%20are%20paid%20as%20fee%0A%20%20%20%20%20%20%20%20costs%20%3D%200.0001%20*%20(state.trades.abs()%20*%20state.prices).sum()%0A%20%20%20%20%20%20%20%20b.aum%20%3D%20state.aum%20-%20costs%0A%0A%20%20%20%20portfolio%20%3D%20b.build()%0A%20%20%20%20return%20(portfolio%2C)%0A%0A%0A%40app.cell%0Adef%20_(portfolio)%3A%0A%20%20%20%20%22%22%22Plot%20the%20portfolio's%20net%20asset%20value%20(NAV)%20over%20time.%0A%0A%20%20%20%20This%20cell%20visualizes%20the%20performance%20of%20the%20pairs%20trading%20strategy%0A%20%20%20%20by%20plotting%20the%20portfolio's%20NAV%20over%20the%20simulation%20period.%0A%0A%20%20%20%20Parameters%0A%20%20%20%20----------%0A%20%20%20%20portfolio%20%3A%20Portfolio%0A%20%20%20%20%20%20%20%20The%20portfolio%20object%20built%20by%20the%20previous%20cell%0A%0A%20%20%20%20%22%22%22%0A%20%20%20%20portfolio.nav.plot()%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
cf3c1c447cfe8f4936eea6ef05fa11fc8d8ce8927b64495687b86e58c7836ae2