cvxgrp / cvxportfolio

Portfolio optimization and back-testing.
https://www.cvxportfolio.com
Apache License 2.0
930 stars 243 forks source link

Example request - Margin in a different currency #135

Open andrewcz opened 5 months ago

andrewcz commented 5 months ago

Hi @enzbus,

Amazing project! really interesting.

Would it be possible to add an example where you've used margin from multiple currencies, accounting for both interest rates and fees? Additionally, showcasing the daily margin call amount based on currency fluctuations. I think this would be interesting from a risk perspective. Best regards,

Andrew

enzbus commented 5 months ago

Hello, and thanks. Example strategies in other (non-US) markets are in the works (PR #127), main issue is improving cleaning logic of Yahoo Finance historical data (I encountered issues on a few FTSE100 names with phony old open prices, ...). Regarding cost of financing (interest rates) FRED provides data at least for EUR, JPY, GBP, and these can already be used as cash_key. More complicated setups (multi-currency, multi-markets with different trading times, non-convex margin or borrow cost, ...), won't probably be supported in the main library, but can be developed with user-defined custom derived classes of MarketData, HoldingCost, .... Another problem with strategies heavy on borrowing is that historical borrow fees of stocks are not publicly available, so it's difficult to develop credible examples. There are some (market neutral with borrow cost and market neutral without borrow cost), but they should be taken with a grain of salt.

PS If you have a specific example strategy in mind feel free to open a PR, even if it includes a user-defined subclass of HoldingCost (which I think is what you mean, but I'm not sure) it would be a good addition to the examples suite.

andrewcz commented 5 months ago

Thank you @enzbus ! much appreciated. I do have one in mind. Let me try and through something together and open a PR. Cheers, Andrew

andrewcz commented 5 months ago

Hi @enzbus I hope your well. I am not sure if this is the best place to ask this question, but setting up a static portfolio - so a portfolio with fixed weights. leveraged with a cross currency - so borrowing jpy to invest in say us stocks - keeping track of interest rate, fees, margin calls (say 1.1 times the borrowed amount), currency exchange and re-balancing monthly to maintain the the leverage ratio is quite challenging and is (surprisingly) non trivial. I am having a bit trouble pulling together a working solutions. Do you have any advice or thoughts. Would be great to get your comments on the above. Best, Andrew

enzbus commented 5 months ago

That sounds interesting @andrewcz ; apologies if I repeat it but I would suggest that you put together your current code in a prototype example, open a PR, and we take it from there. Of course don't include any IP you wish to keep private. It sounds like the cash_key would by JPYEN, which is already supported, and we would derive from DownloadedMarketData to rebase the assets' returns in JPY, using FixedWeights (or Uniform) as example policy. Then we can see if also HoldingCost needs to be derived or we can use the default one...

enzbus commented 5 months ago

PS this is the series currently used as interest rate for JPY, expressed in annualized percentage. Is that right?

andrewcz commented 5 months ago

Thank you @enzbus !! Will put together a code example by the end of the week,as well as further details

andrewcz commented 5 months ago

Hi @enzbus just advise created a pull request with my attempt. Cheers Andrew

enzbus commented 5 months ago

Thanks! Looks great, I added a few comments. Give me write permission to your branch if you wish, happy to help. Looks like we can use that MarketData subclass to prototype future extension of MarketData to handle multi-currency portfolios :)

andrewcz commented 5 months ago

@enzbus !!! amazing!! you legend! I think i have successfully added you as a collaborator. Feel free to make any changes :). Cheers, Andrew

enzbus commented 5 months ago

Sure, I can clean up the way MarketData does FX conversion, eventually that will go in the main library. But you should spend some time on documenting what it is that you want to do, and possibly find references on how margin should calculated, and financing charges. From a quick search I found this https://www.interactivebrokers.com/webinars/Mechanics_of_Overseas_Trade.pdf , it seems in this case financing is charged with the interest rate of the country the stock is from, not the country you buy it from. I'm not going to speculate, so please do find references or clearly state the problem setting and assumptions. Thanks!

andrewcz commented 5 months ago

Hi @enzbus I have done some further thinking, curious on your thoughts on the below.

Main strategy A set of fixed weights on assets (or optimized weights), I think fixed is a good starting point. Borrowed jpy to invest in asset for leverage. Leverage 1:3.5 (3.5 dollars for every 1 dollar invested. If portfolio goes to 1:4.2 (4.2 dollar for every 1 dollar invested) bring portfolio back to leverage 2 above If portfolio goes to 1:2.8 (2.8 dollars for every 1 dollar invested) bring portfolio back to 2 (the 3.5 dollars for every 1 dollar invested), portfolio buys assets to the point of the setting of the If the portfolio is margin called (portfolio is 6 dollars for every 1 dollar invested) the portfolio sells assets until it moves to 1:3.5

Risks and costs. Interest rate risk of JPY. (noted and taken), this has been checked, if in interactive brokers you submit an order to buy say SPY, and you attach a jpy/usd order you will be charged the interest rate on jpy and also take the currency risk of jpy to usd, calculated daily.
Currency risk of jpy to usd. (noted and taken), calculated daily as this affects the margin ratio, this should be incorporated into the margin calculation (?). Transaction costs (noted and could be modelled) Bid ask spread or liquidity risk, could this be modelled (?), if the portfolio has to sell what price will it get.

enzbus commented 5 months ago

OK, this looks reasonable. Let's take an example.

target_weights = {'AAPL':1, 'SPY':0.5, 'JPYEN':-0.5}

Remember that in Cvxportfolio weights always sum to 1, because of the self-financing condition. The above has leverage 1.5, leverage is just the sum of absolute values of non-cash weights.

If we want to leverage up the above to, say, leverage 3, you would get

target_weights = {'AAPL':2, 'SPY':1, 'JPYEN':-2}

Which is obtained by simply multiplying the non-cash part and adjusting the cash account accordingly.

So, the subclass of FixedWeights would calculate the current leverage (it receives current_weights) and scale the target weights according to some logic like the one you describe. This happens inside its values_in_time method.

andrewcz commented 5 months ago

Amazing @enzbus !! Im just heading home from work. Will jump on and build an example.im pretty sure we should be able to close this tonight. Best, Andrew

andrewcz commented 5 months ago

Hi @enzbus , I have made a new file names leverage_strategy.py - i am getting an error and hence im a little stuck. In the long term i plan also to add modelling bid ask spread in terms of liquidity risk.