{"action":"created","issue":{"url":"https://api.github.com/repos/QuantConnect/Lean/issues/2060","repository_url":"https://api.github.com/repos/QuantConnect/Lean","labels_url":"https://api.github.com/repos/QuantConnect/Lean/issues/2060/labels{/name}","comments_url":"https://api.github.com/repos/QuantConnect/Lean/issues/2060/comments","events_url":"https://api.github.com/repos/QuantConnect/Lean/issues/2060/events","html_url":"https://github.com/QuantConnect/Lean/issues/2060","id":328387172,"node_id":"MDU6SXNzdWUzMjgzODcxNzI=","number":2060,"title":"Support indirect/multi-leg currency conversions ( A->{Bridge Currencies}->B )","user":{"login":"mchandschuh","id":531416,"node_id":"MDQ6VXNlcjUzMTQxNg==","avatar_url":"https://avatars2.githubusercontent.com/u/531416?v=4","gravatar_id":"","url":"https://api.github.com/users/mchandschuh","html_url":"https://github.com/mchandschuh","followers_url":"https://api.github.com/users/mchandschuh/followers","following_url":"https://api.github.com/users/mchandschuh/following{/other_user}","gists_url":"https://api.github.com/users/mchandschuh/gists{/gist_id}","starred_url":"https://api.github.com/users/mchandschuh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mchandschuh/subscriptions","organizations_url":"https://api.github.com/users/mchandschuh/orgs","repos_url":"https://api.github.com/users/mchandschuh/repos","events_url":"https://api.github.com/users/mchandschuh/events{/privacy}","received_events_url":"https://api.github.com/users/mchandschuh/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-06-01T05:32:01Z","updated_at":"2018-06-01T23:53:24Z","closed_at":null,"author_association":"MEMBER","body":"<!--- This template provides sections for bugs and features. Please delete any irrelevant sections before submitting -->\r\n\r\n#### Expected Behavior\r\n<!--- Required. Describe the behavior you expect to see for your case. -->\r\nThe system is able to handle currency pairs that are not directly convertible into the account currency\r\n\r\n#### Actual Behavior\r\n<!--- Required. Describe the actual behavior for your case. -->\r\nThe system is unable to perform currency conversions if it can't find a direct pair leading back to the account currency. On crypto exchanges, it's normal fare for currencies/tokens to not be directly convertible to fiat of any kind, for example, on binance *no* coins are directly convertible to fiat (USDT doesn't count :) ). In such cases we need to move through a 'bridge' currency, such as BTC and then can use a BTCUSD rate (maybe even a BTCUSDT if it's the best available), in order to price securities in terms of dollars (or whatever your account currency may be).\r\n\r\nThis can get unwieldy if you consider the above example but for an account currency of EUR. We now would require three 'legs', an additional one to move from USD (or USDT) to EUR, unless of course the exchange provides a BTCEUR pair of it's own to skip the USD middleman.\r\n\r\n#### Potential Solution\r\n<!--- Optional. Describe any potential solutions and/or thoughts as to what may be causing the difference between expected and actual behavior. -->\r\n> The below may have spiraled into stream of consciousness but I think the comments shed some light on some potential issues/solutions/paths forward so it's left unaltered.\r\n\r\nI think to start we should list the various concerns and cases. The main issue I see here is that it's potentially unbounded (the number of potential paths from A->...>B) and may also be temporal, IOW, if there's multiple paths how do you choose which path is the right one (and be consistent!), so things like using market cap (or volume) to give preference to particular currencies to act as 'bridge' currencies can lead to different paths depending on market movement (which might actually be the right thing to do?).\r\n\r\nAnother thought is first limiting the unbounded aspect (say max of 3 hops? A -> Bridge1 -> Bridge2 -> B, maybe 4?) and could compute a range of potential conversion rates and pull the mean (would require some work to how we pull conversion rates)... I think in all cases the fact that we currently use the security's current price for the conversion rate should be decoupled so that there's a component that provides conversion rates (perhaps `IConversionRateProvider`) and he just so happens to be initialized with some securities, so a refactoring step could be creating this abstraction and implementing for the existing direct case A->B and then expand on that for cases where we require multiple hops.\r\n\r\n#### Checklist\r\n<!--- Confirm that you've provided all the required information. -->\r\n<!--- Required fields --->\r\n- [x] I have completely filled out this template\r\n- [x] I have confirmed that this issue exists on the current `master` branch\r\n- [x] I have confirmed that this is not a duplicate issue by searching [issues](https://github.com/QuantConnect/Lean/issues)\r\n\r\n<!--- Template inspired by https://github.com/stevemao/github-issue-templates -->"},"comment":{"url":"https://api.github.com/repos/QuantConnect/Lean/issues/comments/394037781","html_url":"https://github.com/QuantConnect/Lean/issues/2060#issuecomment-394037781","issue_url":"https://api.github.com/repos/QuantConnect/Lean/issues/2060","id":394037781,"node_id":"MDEyOklzc3VlQ29tbWVudDM5NDAzNzc4MQ==","user":{"login":"viliwonka","id":4028544,"node_id":"MDQ6VXNlcjQwMjg1NDQ=","avatar_url":"https://avatars3.githubusercontent.com/u/4028544?v=4","gravatar_id":"","url":"https://api.github.com/users/viliwonka","html_url":"https://github.com/viliwonka","followers_url":"https://api.github.com/users/viliwonka/followers","following_url":"https://api.github.com/users/viliwonka/following{/other_user}","gists_url":"https://api.github.com/users/viliwonka/gists{/gist_id}","starred_url":"https://api.github.com/users/viliwonka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/viliwonka/subscriptions","organizations_url":"https://api.github.com/users/viliwonka/orgs","repos_url":"https://api.github.com/users/viliwonka/repos","events_url":"https://api.github.com/users/viliwonka/events{/privacy}","received_events_url":"https://api.github.com/users/viliwonka/received_events","type":"User","site_admin":false},"created_at":"2018-06-01T23:53:24Z","updated_at":"2018-06-01T23:53:24Z","author_association":"NONE","body":"> I think to start we should list the various concerns and cases. The main issue I see here is that it's potentially unbounded (the number of potential paths from A->...>B) and may also be temporal, IOW, if there's multiple paths how do you choose which path is the right one (and be consistent!), so things like using market cap (or volume) to give preference to particular currencies to act as 'bridge' currencies can lead to different paths depending on market movement (which might actually be the right thing to do?).\r\n\r\nSo ok, this one may not be so hard. I came up with something:\r\n\r\nYou have graph `G` with bidirectional connections. `G` holds all known assets and pairs. \r\nRemember, node is asset, connection is pair.\r\n\r\nYou have `X` node and `Y` node. Example `X` = `REN`, `Y` = `USD`.\r\nX and Y represent target pair you want to calculate.\r\n\r\nAnd then you have list `P`. This list holds `Path`s, for example `REN-ETH-USD`.\r\n\r\nOk, now all you do is repeat this process:\r\n\r\n1. Find shortest path `p` from `X` to `Y` in graph `G`. If none found, terminate.\r\n2. Remove path `p` from `G` (remove connections), and add it to list `P` (nodes and connections)\r\n3. Go to step 1.\r\n\r\nThat is, you should be left with all possible paths. The graph `G` will be left with un-related pairs and could be removed.\r\n\r\nAnd `p` shouldn't hold any non-sense paths like 'REN-ZRX-ETH-BTC-USD'.\r\n\r\nI am not sure what is metric/heuristic `d(x,y)` for shortest path yet, it can just be \"hops between X and Y\", or if it should include volume. \r\n"}}
{"actor":{"display_login":"viliwonka"}}