bankroll-py / bankroll Goto Github PK
View Code? Open in Web Editor NEWIngest portfolio and other data from multiple brokerages, and analyze it
License: MIT License
Ingest portfolio and other data from multiple brokerages, and analyze it
License: MIT License
APIs like IB's will likely be faster to fetch data for a bunch of contracts at once, as opposed to one-by-one.
Not sure why, haven't looked into it
e.g. use of ~
to represent the home directory
Options aren't printing their cost basis even when the underlying is. Inspection of debug logging shows that IB is correctly returning an average price for the options, so not sure what's going on.
This will require carefully conditionalizing all imports of ib_insync
, as even just touching it will check that ibapi
is installed.
This would make bankroll
less useful today, but once we have alternative data sources (e.g., #32), it could make getting started much easier.
The camel-casing is not very conventional right now.
We can use progress
for this.
Realized basis only makes sense for the lifetime of a position, so whenever one is fully closed out, it should reset—and then if a new position is opened in the same symbol, the cost accounting should start over there.
Example is present in fidelity_transactions.csv
.
e.g., with --verbose
enabled:
Downloading Activity report |INFO:ib_insync.flexreport:still working...
Downloading Activity report /INFO:ib_insync.flexreport:still working...
Downloading Activity report -INFO:ib_insync.flexreport:still working...
Downloading Activity report \INFO:ib_insync.flexreport:still working...
Downloading Activity report |INFO:ib_insync.flexreport:still working...
Downloading Activity report /INFO:ib_insync.flexreport:still working...
Downloading Activity report -INFO:ib_insync.flexreport:still working...
Downloading Activity report \INFO:ib_insync.flexreport:still working...
Downloading Activity report |INFO:ib_insync.flexreport:still working...
Downloading Activity report /INFO:ib_insync.flexreport:still working...
Downloading Activity report -INFO:ib_insync.flexreport:still working...
Downloading Activity report \INFO:ib_insync.flexreport:still working...
Downloading Activity report |INFO:ib_insync.flexreport:still working...
Downloading Activity report /INFO:ib_insync.flexreport:still working...
Downloading Activity report -INFO:ib_insync.flexreport:still working...
Downloading Activity report \INFO:ib_insync.flexreport:still working...
Downloading Activity report |INFO:ib_insync.flexreport:still working...
Downloading Activity report /INFO:ib_insync.flexreport:still working...
Downloading Activity report -INFO:ib_insync.flexreport:still working...
Downloading Activity report \INFO:ib_insync.flexreport:still working...
Downloading Activity report |INFO:ib_insync.flexreport:still working...
Downloading Activity report /INFO:ib_insync.flexreport:still working...
If it's not enabled this way, the spinner hangs for quite a while.
e.g., ES
might say something like SPX
, while single-stock futures will naturally use the underlying stock. This may be relevant for calculating the realizedBasis
of a security.
Without any settings established or command-line arguments, this error occurs:
> python -m bankroll positions
File "bankroll\brokers\ibkr.py", line 842, in fromSettings
trades=trades,
UnboundLocalError: local variable 'trades' referenced before assignment
Fuzz test failing for IB validatePositionContract when comparing position's contract multiplier to contract multiplier.
Support pulling the mark-to-market values of all positions, using a live IB connection.
There should be enough information in a (complete) transaction log to reconstruct which lots were bought and sold when, which may be useful for tax or other purposes.
This breaks our parser. We should make it more forward-compatible.
Attempting to parse IB positions including TBills fails with "ValueError: Unrecognized/unsupported security type"
If Settings
enums could be defined with enough context to present meaningful CLI information, we could use Settings.__subclasses__()
to get rid of the manual argument generation in __main__.py
, which would simplify the code and make extension easier.
e.g., --schwab-transactions
instead of --schwabtransactions
Seems like an interesting alternative to an IB connection for real data: https://www.alphavantage.co
IB's Python API is not well-typed or well-documented, so there will likely be tons of corner cases in our parsing code. We should have a set of fuzz tests that yield complete crap, just to make sure that our parsing will handle whatever gets thrown at it. (We can use hypothesis
for this, like our property-based tests.)
It will be hard to calculate a "true" Expected Value because we don't know how often a particular strategy "should" win (simulations will not be accurate if some strategies are premised on news events or market psychology), but perhaps we could draw conclusions about how often a particular shape of strategy has worked for the user, then feed in the win/lose amounts to determine a sort of historical EV.
Not just trades. This should probably involve refactoring Trade
into a hierarchy of classes, and getting rid of TradeFlags
entirely.
Exclude the CLI, etc. Basically, package it up as if we were shipping it to PyPI.
It'd be nice to populate some kind of "broker loader" with the right settings to find whatever data it needs (an IB
connection, for example, or file paths for other brokers), and then allow consumers to lazily consume information like positions, activity, etc.—effectively standardizing the read interface for all broker modules.
This might also decouple DataAggregator
from some of the implementation details, which would be nice.
Example is present in schwab_transactions.CSV
.
I was thinking that it might be useful to support a concept of plugins, in the form of (at least) additional verbs for the command-line, similarly to other CLI tools.
A motivating example could be: a separate project which adds a bankroll
command for offline storage and syncing of activity logs.
We've implemented a bunch of really basic operations like __repr__
and __eq__
in our models. Let's use the @dataclass
decorator as much as possible instead.
If possible, it'd be neato for the DESIRED_ALLOCATION
setting to be pulled from an INI file instead, to make the notebook actually generically useful without hackery.
Follow the example in their docs: https://hypothesis.readthedocs.io/en/latest/settings.html#settings-profiles
Right now, we just have documentation comments, instead of conventional docstrings.
Knowing how much "spare" cash is lying about would be handy for rebalancing, for example.
Like a spreadsheet
Traceback (most recent call last):
…
return _forceParseSchwabTransaction(t, flags=flagsByAction[t.action])
KeyError: 'Non-Qualified Div'
Seems wrong, but needs more investigation. (Details redacted as it's a real portfolio position.)
This would make it useful for, e.g., synthetic long and short positions, or futures.
Could be neat as a Jupyter notebook
Net P/L % is incorrectly reported as negative if the realized basis is negative, but current value positive. The magnitude of the number is likely wrong too.
Securities denominated in GBP (pound sterling) are often actually denominated in GBX (pence sterling), and the reporting of this through IB's API is unclear. Currently we're showing GBX values as GBP, grossly overinflating the actual value.
Error 321, reqId -1: Error validating request:-'b7' : cause - The API interface is currently in Read-Only mode.
We probably need to use ib_insync
's new readonly=True
flag to IB.connect
.
Across short options positions, offset by opposing positions
Calculate total exposure to countries (or maybe regions, generally) based on positions and cash held.
In trying to build another project which wants to use pieces of bankroll, I'm finding the current structure kind of unwieldy, and don't want to risk this becoming a kitchen sink. At bare minimum, we should probably separate the model from the brokerage support from the analysis and tools.
Something like this, although not necessarily as finely-sliced:
digraph {
rankdir = BT;
{ rank = min; model; }
{ rank = same; ibkr; schwab; fidelity; vanguard; }
{ rank = same; analysis, "plugin framework" }
{ rank = max; cli, notebooks }
ibkr, schwab, fidelity, vanguard -> model
ibkr, schwab, fidelity, vanguard -> "plugin framework" [style=dashed]
analysis -> model
notebooks -> analysis, "plugin framework"
cli -> analysis, "plugin framework"
}
I get this error when attempting to run bankroll (even simple --help) after install in a fresh conda virtual environment (python 3.6).
$ bankroll --help
Traceback (most recent call last):
File "c:\users\lee\anaconda3\envs\foliolyze\lib\runpy.py", line 193, in run_module_as_main
"main", mod_spec)
File "c:\users\lee\anaconda3\envs\foliolyze\lib\runpy.py", line 85, in run_code
exec(code, run_globals)
File "C:\Users\lee\Anaconda3\envs\foliolyze\Scripts\bankroll.exe_main.py", line 5, in
File "c:\users\lee\anaconda3\envs\foliolyze\lib\site-packages\bankroll\interface_init.py", line 1, in
from bankroll.analysis import *
File "c:\users\lee\anaconda3\envs\foliolyze\lib\site-packages\bankroll\analysis_init_.py", line 1, in
from .analysis import (
File "c:\users\lee\anaconda3\envs\foliolyze\lib\site-packages\bankroll\analysis\analysis.py", line 88
raise ValueError(f"Unexpected type of activity: {activity}")
I think I've come up with a structured format that should work as a reusable trade journal, which could conveniently be joined/informed by bankroll activity logs. Assigning to myself to work out the details.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.