Welcome to invertimo
14 |15 | Let's see how your investments are doing... 16 |
17 | 18 | 22 | 23 | Continue with 24 | Google 25 | 26 | 27 |├── assets ├── event_list.css ├── account_value.css ├── select_positions.css ├── routing.js ├── components │ ├── IconWithText.js │ ├── position_link.css │ ├── ImportButton.js │ ├── RecordButton.js │ ├── Snackbar.js │ ├── SubmitSpinnerButton.js │ ├── EventTypeDisplay.js │ ├── DatePicker.js │ ├── PositionLink.js │ ├── AreaChart.js │ ├── Stepper.js │ ├── Stepper.test.js │ └── SplitButtonNav.js ├── display_utils.js ├── display_utils.test.js ├── currencies.js ├── index.js ├── transaction_list.css ├── forms │ ├── utils.test.js │ ├── utils.js │ ├── styles.js │ ├── DeleteDialog.js │ └── CreateAccountForm.js ├── App.js ├── error_utils.js ├── SelectPositions.js ├── colors.js ├── AccountValues.js ├── assetOptions.js ├── TimeSelector.js ├── theme.js ├── TransactionImportList.js ├── Reports.js ├── TransactionImportDetail.js ├── Events.js ├── position_list.css ├── Header.js ├── LotList.js ├── TransactionImportResult.js ├── PositionList.js ├── TransactionDetail.test.js └── TransactionImportRecord.js ├── finance ├── __init__.py ├── integrations │ └── __init__.py ├── migrations │ ├── __init__.py │ ├── 0024_alter_lot_sell_date.py │ ├── 0017_alter_asset_tracked.py │ ├── 0014_auto_20210815_1653.py │ ├── 0007_alter_account_balance.py │ ├── 0008_alter_account_last_modified.py │ ├── 0030_alter_transaction_quantity.py │ ├── 0013_alter_transaction_order_id.py │ ├── 0005_position_quantity.py │ ├── 0022_accountevent_withheld_taxes.py │ ├── 0004_alter_transaction_transaction_costs.py │ ├── 0028_alter_transactionimport_integration.py │ ├── 0010_currencyexchangerate_value.py │ ├── 0015_alter_asset_exchange.py │ ├── 0020_accountevent_event_type.py │ ├── 0037_alter_eventimportrecord_transaction.py │ ├── 0027_transactionimport_account.py │ ├── 0035_auto_20220130_1802.py │ ├── 0039_auto_20220226_1240.py │ ├── 0025_auto_20211102_1819.py │ ├── 0012_auto_20210725_1745.py │ ├── 0016_auto_20210822_1041.py │ ├── 0019_auto_20210822_1952.py │ ├── 0011_auto_20210529_0945.py │ ├── 0003_auto_20210427_1419.py │ ├── 0029_auto_20220121_1709.py │ ├── 0021_auto_20210929_1246.py │ ├── 0002_auto_20210426_1145.py │ ├── 0018_auto_20210822_1117.py │ ├── 0032_auto_20220129_1631.py │ ├── 0036_auto_20220202_1101.py │ ├── 0006_auto_20210503_1358.py │ ├── 0034_auto_20220130_1743.py │ ├── 0031_auto_20220122_1352.py │ ├── 0009_currencyexchangerate_pricehistory.py │ ├── 0040_auto_20220402_1814.py │ ├── 0033_eventimportrecord.py │ ├── 0026_transactionimport_transactionimportrecord.py │ ├── 0023_auto_20211028_1835.py │ ├── 0038_auto_20220203_1112.py │ └── 0001_initial.py ├── apps.py ├── binance_transaction_sample_with_income_mini.csv ├── tasks.py ├── binance_transaction_only_usd.csv ├── admin.py ├── transactions_example_latest_bad_columns.csv ├── transactions_example_latest.csv ├── binance_transaction_sample_mismatched_dates.csv ├── transactions_example_latest_renamed.csv ├── management │ └── commands │ │ ├── fetch_prices.py │ │ └── import_transactions.py ├── transactions_example_short.csv ├── binance_transaction_sample_odd.csv ├── binance_transaction_sample_dates_slight_offset.csv ├── binance_transaction_sample.csv ├── utils.py ├── binance_transaction_sample_with_income.csv ├── assets.py ├── testing_utils.py └── test_prices.py ├── invertimo ├── __init__.py ├── celery.py ├── asgi.py ├── wsgi.py ├── views.py └── urls.py ├── static ├── gains.png ├── cupcake.png ├── dollars.jpeg ├── favicon.ico ├── degiro_export.png ├── favicon-16x16.png ├── favicon-32x32.png ├── transactions.png ├── Comfortaa-Medium.ttf ├── OpenSans-Regular.ttf ├── account_overview.png ├── apple-touch-icon.png ├── base_internal.css ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── site.webmanifest ├── landing.css └── login.css ├── .gitmodules ├── babel.config.js ├── templates ├── index.html ├── login.html ├── signup.html ├── base_internal.tmpl.html ├── base.html ├── privacy_policy.html └── landing.html ├── deployment ├── app │ ├── docker_entrypoint.sh │ └── docker_entrypoint.dev.sh ├── invertimo.com_docker_compose.service ├── staging.invertimo.com_docker_compose.service ├── setup_remote.sh ├── Readme.md ├── staging.invertimo.com.nginx.conf └── invertimo.com.nginx.conf ├── .dockerignore ├── requirements.in ├── docker-compose.yml ├── .eslintrc.js ├── manage.py ├── setup.cfg ├── docker-compose.prod.yml ├── docker-compose.dev.yml ├── docker-compose.staging.yml ├── Dockerfile ├── LICENSE ├── webpack.config.js ├── README.md ├── .gitignore └── package.json /assets/event_list.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /finance/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /finance/integrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /finance/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /invertimo/__init__.py: -------------------------------------------------------------------------------- 1 | from .celery import app as celery_app 2 | 3 | __all__ = ("celery_app",) -------------------------------------------------------------------------------- /static/gains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/gains.png -------------------------------------------------------------------------------- /static/cupcake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/cupcake.png -------------------------------------------------------------------------------- /static/dollars.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/dollars.jpeg -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/favicon.ico -------------------------------------------------------------------------------- /static/degiro_export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/degiro_export.png -------------------------------------------------------------------------------- /static/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/favicon-16x16.png -------------------------------------------------------------------------------- /static/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/favicon-32x32.png -------------------------------------------------------------------------------- /static/transactions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/transactions.png -------------------------------------------------------------------------------- /static/Comfortaa-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/Comfortaa-Medium.ttf -------------------------------------------------------------------------------- /static/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /static/account_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/account_overview.png -------------------------------------------------------------------------------- /static/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/apple-touch-icon.png -------------------------------------------------------------------------------- /static/base_internal.css: -------------------------------------------------------------------------------- 1 | 2 | .main { 3 | padding: 0; 4 | } 5 | 6 | .button { 7 | padding: 10px; 8 | } -------------------------------------------------------------------------------- /static/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/android-chrome-192x192.png -------------------------------------------------------------------------------- /static/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilonajulczuk/invertimo/HEAD/static/android-chrome-512x512.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deployment/secrets"] 2 | path = deployment/secrets 3 | url = git@github.com:ilonajulczuk/invertimoenv.git 4 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@babel/preset-env', 4 | '@babel/preset-react', 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /assets/account_value.css: -------------------------------------------------------------------------------- 1 | 2 | .account-value-data-chart { 3 | height: 400px; 4 | } 5 | 6 | .account-value-charts { 7 | margin-top: 2em; 8 | margin-bottom: 2em; 9 | } -------------------------------------------------------------------------------- /finance/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FinanceConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'finance' 7 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base_internal.webpack.html' %} 2 | {% load static %} 3 | {% block content %} 4 |
5 | 6 | {{ user.email|json_script:'userEmail' }} 7 | 8 | {% endblock %} -------------------------------------------------------------------------------- /deployment/app/docker_entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | /usr/src/venv/bin/python3.8 manage.py migrate --noinput 3 | /usr/src/venv/bin/python3.8 manage.py collectstatic --noinput 4 | /usr/src/venv/bin/gunicorn -b 0.0.0.0:8000 --workers 4 --timeout 300 invertimo.wsgi -------------------------------------------------------------------------------- /deployment/app/docker_entrypoint.dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | /usr/src/venv/bin/python3.8 manage.py migrate --noinput 3 | /usr/src/venv/bin/python3.8 manage.py collectstatic --noinput 4 | npx webpack --mode=development --watch & 5 | /usr/src/venv/bin/python3.8 manage.py runserver 0.0.0.0:8000 -------------------------------------------------------------------------------- /static/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /invertimo/celery.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from celery import Celery 4 | 5 | 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "invertimo.settings") 7 | 8 | app = Celery("invertimo") 9 | app.config_from_object("django.conf:settings", namespace="CELERY") 10 | app.autodiscover_tasks() -------------------------------------------------------------------------------- /assets/select_positions.css: -------------------------------------------------------------------------------- 1 | .select-positions-li { 2 | display: flex; 3 | padding: 10px; 4 | margin-right: 5px; 5 | margin-bottom: 5px; 6 | border-radius: 5px; 7 | border: 1px solid #ccc; 8 | } 9 | 10 | .display-flex { 11 | display: flex; 12 | flex-wrap: wrap; 13 | } -------------------------------------------------------------------------------- /static/landing.css: -------------------------------------------------------------------------------- 1 | .main { 2 | text-align: center; 3 | max-width: 1300px; 4 | } 5 | 6 | .grid-container { 7 | grid-template-rows: 120px 1fr 120px; 8 | } 9 | 10 | @media only screen and (min-width: 350px) { 11 | .grid-container { 12 | grid-template-rows: 100px 1fr 120px; 13 | } 14 | } -------------------------------------------------------------------------------- /assets/routing.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | useLocation 4 | } from "react-router-dom"; 5 | 6 | // A custom hook that builds on useLocation to parse 7 | // the query string for you. 8 | export function useQuery() { 9 | const { search } = useLocation(); 10 | 11 | return React.useMemo(() => new URLSearchParams(search), [search]); 12 | } -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | invertimoenv 2 | venv2 3 | node_modules/ 4 | data/ 5 | 6 | # Distribution / packaging 7 | .Python 8 | build/ 9 | develop-eggs/ 10 | dist/ 11 | downloads/ 12 | eggs/ 13 | .eggs/ 14 | lib/ 15 | lib64/ 16 | parts/ 17 | sdist/ 18 | var/ 19 | wheels/ 20 | pip-wheel-metadata/ 21 | share/python-wheels/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | MANIFEST 26 | *index-bundle* -------------------------------------------------------------------------------- /assets/components/IconWithText.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import PropTypes from 'prop-types'; 4 | import Icon from '@mui/material/Icon'; 5 | 6 | export default function IconWithText({icon, text}) { 7 | return <>15 | Let's see how your investments are doing... 16 |
17 | 18 | 22 | 23 | Continue with 24 | Google 25 | 26 | 27 |Your account will be created when you sign in for the first time.
15 | 16 | 20 | 21 | Continue with 22 | Google 23 | 24 | 25 | 26 |By signing in you are agreeing to the privacy 29 | policy.
30 |Still fetching data for remaining accounts...
; 28 | } 29 | return11 | This privacy policy will explain how Invertimo (this website) uses the personal data we collect from you 12 | when 13 | you use our website. 14 |
15 |16 | Data that you provide on the website is encrypted in transit (HTTPS) and at rest (stored in database that 17 | encrypts it). 18 |
19 |20 | The data that you provide through various forms is not used for any other purposes than the Invertimo 21 | services that are provided to you. 22 | Some of your data, e.g. if you use certain feature might be used for decisions to improve the app itself. 23 |
24 |25 | We might contact you about your experience with the app by using the email you used in the application. 26 |
27 |28 | We use error tracking software called sentry. If you encounter an error, 29 | the problematic request will be securely stored in sentry.io Invertimo project and available for later 30 | inspection so that we can prevent errors like this from happening in the future. 31 |
32 |33 | If you delete your account, all associated data will be deleted. When you delete things from the 34 | application, they are deleted. 35 | We store about 1 month of backup data, but don't perform regular backups. 36 |
37 |If you have more questions please contact justyna@invertimo.com
38 |This form helps you record income you received from staking or savings interest. If you use Binance, you can instead use automatic import here.
42 |Track your portfolio across different accounts, with assets in different currencies easily.
9 |10 |
You can import your transactions and info about other events (e.g. dividend payouts, crypto staking payouts or saving interest) 15 | to invertimo using either manual or automated import.
16 |17 | Invertimo supports batch upload from Degiro (biggest European brokerage) and from Binance (one of the biggest crypto exchanges). 18 |
19 |20 | More integrations are planned in the future. 21 |
22 | Get started for free 23 |
26 | It's easy to lose track of all your transactions and get confused with currency exchange rates.
33 |On top of that in some countries such as Ireland, funds are taxed differently than stocks and 34 | you have to deal with deemed disposal and pay taxes from unrealized gains.
35 |Invertimo is perfect for an any investor with diverse assets, e.g in Euro, USD, GBP and crypto.
36 | Try it 37 | 38 |
41 | 51 | Invertimo automatically fetches prices for recognized assets and can help you 52 | better understand your portfolio over time. 53 |
54 |
57 | 64 | The code is open source and can be found on github. 65 |
66 |67 | Developed by @attilczuk. 68 |
69 |Do you have any suggestions? Send them to justyna@invertimo.com
70 |68 | Executed at: {createdAt} 69 |
70 |{successfulRawRecords.length} successful records, {successfulRawRecordsDuplicates.length} of which duplicates.
72 |{failedRawRecords.length} failed records.
73 | 74 | {successfulRawRecords.length ?{successfulRawEventRecords.length} successful records, {successfulRawEventRecordsDuplicates.length} of which duplicates.
80 |{failedRawEventRecords.length} failed records.
81 | 82 | {successfulRawEventRecords.length ?