mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-28 21:12:16 +00:00
Portoflio : add pa export command for Degiro (#2065)
* Portoflio : add pa export command for Degiro * Update controller + tests * Tests * Degiro : update pa export format * Fixing Premium * Black * Show index
This commit is contained in:
1
i18n/en.yml
vendored
1
i18n/en.yml
vendored
@@ -1014,6 +1014,7 @@ en:
|
||||
portfolio/bro/degiro/companynews: view news about a company with it's isin
|
||||
portfolio/bro/degiro/lastnews: view latest news
|
||||
portfolio/bro/degiro/topnews: view top news preview
|
||||
portfolio/bro/degiro/paexport: csv export for portfolio analysis
|
||||
portfolio/bro/rh/login: login to robinhood
|
||||
portfolio/bro/rh/holdings: show account holdings in stocks
|
||||
portfolio/bro/rh/history: show equity history of your account
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# IMPORTATION STANDARD
|
||||
import argparse
|
||||
import datetime
|
||||
import logging
|
||||
from typing import List
|
||||
|
||||
@@ -9,6 +10,10 @@ from prompt_toolkit.completion import NestedCompleter
|
||||
# IMPORTATION INTERNAL
|
||||
from openbb_terminal import feature_flags as obbff
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
EXPORT_ONLY_RAW_DATA_ALLOWED,
|
||||
valid_date,
|
||||
)
|
||||
from openbb_terminal.menu import session
|
||||
from openbb_terminal.parent_classes import BaseController
|
||||
from openbb_terminal.portfolio.brokers.degiro.degiro_view import DegiroView
|
||||
@@ -31,6 +36,7 @@ class DegiroController(BaseController):
|
||||
"pending",
|
||||
"topnews",
|
||||
"update",
|
||||
"paexport",
|
||||
]
|
||||
PATH = "/portfolio/bro/degiro/"
|
||||
|
||||
@@ -307,3 +313,42 @@ class DegiroController(BaseController):
|
||||
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
||||
|
||||
self.__degiro_view.update(ns_parser=ns_parser)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def call_paexport(self, other_args: List[str]):
|
||||
"""Export transactions for Portfolio Analysis Menu into CSV format."""
|
||||
|
||||
# PARSING ARGS
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="paexport",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--start",
|
||||
help="Start date.",
|
||||
required=True,
|
||||
type=valid_date,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-e",
|
||||
"--end",
|
||||
help="End date.",
|
||||
type=valid_date,
|
||||
default=datetime.datetime.now(),
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--currency",
|
||||
help="Used currency.",
|
||||
default="USD",
|
||||
type=str,
|
||||
)
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
parser,
|
||||
other_args,
|
||||
export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED,
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
self.__degiro_view.transactions_export(ns_parser=ns_parser)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# IMPORTATION STANDARD
|
||||
import datetime
|
||||
import logging
|
||||
import math
|
||||
from typing import Union
|
||||
from typing import List, Union
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pandas as pd
|
||||
@@ -15,6 +16,7 @@ from degiro_connector.trading.models.trading_pb2 import (
|
||||
ProductSearch,
|
||||
ProductsInfo,
|
||||
TopNewsPreview,
|
||||
TransactionsHistory,
|
||||
Update,
|
||||
)
|
||||
|
||||
@@ -336,3 +338,103 @@ class DegiroModel:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_transactions(
|
||||
self, start: datetime.date, end: datetime.date
|
||||
) -> pd.DataFrame:
|
||||
trading_api = self.__trading_api
|
||||
|
||||
from_date = TransactionsHistory.Request.Date(
|
||||
year=start.year,
|
||||
month=start.month,
|
||||
day=start.day,
|
||||
)
|
||||
to_date = TransactionsHistory.Request.Date(
|
||||
year=end.year,
|
||||
month=end.month,
|
||||
day=end.day,
|
||||
)
|
||||
request = TransactionsHistory.Request(
|
||||
from_date=from_date,
|
||||
to_date=to_date,
|
||||
)
|
||||
|
||||
transactions_dict = trading_api.get_transactions_history(
|
||||
request=request,
|
||||
raw=True,
|
||||
)
|
||||
|
||||
transactions_df = pd.DataFrame(transactions_dict["data"])
|
||||
transactions_df["productId"] = transactions_df["productId"].astype("int")
|
||||
|
||||
return transactions_df
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_products_details(self, product_id_list: List[int]) -> pd.DataFrame:
|
||||
trading_api = self.__trading_api
|
||||
|
||||
product_id_list = list(set(product_id_list))
|
||||
|
||||
request = ProductsInfo.Request()
|
||||
request.products.extend(product_id_list)
|
||||
|
||||
products_info = trading_api.get_products_info(
|
||||
request=request,
|
||||
raw=True,
|
||||
)
|
||||
|
||||
products_df = pd.DataFrame(products_info["data"].values())
|
||||
|
||||
return products_df
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_transactions_export(
|
||||
self, start: datetime.date, end: datetime.date, currency: str
|
||||
) -> pd.DataFrame:
|
||||
transactions_df = self.get_transactions(start=start, end=end)
|
||||
product_id_list = list(transactions_df.productId)
|
||||
products_df = self.get_products_details(product_id_list=product_id_list)
|
||||
|
||||
products_df["productId"] = products_df["id"]
|
||||
transactions_df["productId"] = transactions_df["productId"].astype("int")
|
||||
products_df["productId"] = products_df["productId"].astype("int")
|
||||
transactions_full_df = pd.merge(
|
||||
transactions_df,
|
||||
products_df[{"productId", "symbol", "productType"}],
|
||||
on="productId",
|
||||
)
|
||||
|
||||
portfolio_df = transactions_full_df.rename(
|
||||
columns={
|
||||
"date": "Date",
|
||||
"symbol": "Ticker",
|
||||
"productType": "Type", # STOCK or ETF
|
||||
"price": "Price",
|
||||
"quantity": "Quantity",
|
||||
"buysell": "Side", # BUY or SELL
|
||||
"totalFeesInBaseCurrency": "Fees",
|
||||
}
|
||||
)
|
||||
|
||||
portfolio_df["Premium"] = 0
|
||||
portfolio_df["Currency"] = currency
|
||||
portfolio_df["Side"] = portfolio_df["Side"].replace({"S": "SELL", "B": "BUY"})
|
||||
portfolio_df["Date"] = pd.to_datetime(
|
||||
portfolio_df["Date"].str.slice(0, 10)
|
||||
).dt.date
|
||||
columns = [
|
||||
"Date",
|
||||
"Ticker",
|
||||
"Type",
|
||||
"Price",
|
||||
"Quantity",
|
||||
"Fees",
|
||||
"Premium",
|
||||
"Side",
|
||||
"Currency",
|
||||
]
|
||||
portfolio_df = portfolio_df[columns]
|
||||
portfolio_df = portfolio_df.set_index("Date")
|
||||
|
||||
return portfolio_df
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# IMPORTATION THIRDPARTY
|
||||
import logging
|
||||
from argparse import Namespace
|
||||
from pathlib import Path
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pandas as pd
|
||||
@@ -19,6 +20,10 @@ from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.decorators import check_api_key
|
||||
|
||||
# IMPORTATION INTERNAL
|
||||
from openbb_terminal.helper_funcs import (
|
||||
export_data,
|
||||
print_rich_table,
|
||||
)
|
||||
from openbb_terminal.portfolio.brokers.degiro.degiro_model import DegiroModel
|
||||
from openbb_terminal.rich_config import console, MenuText
|
||||
|
||||
@@ -68,6 +73,7 @@ class DegiroView:
|
||||
mt.add_cmd("companynews")
|
||||
mt.add_cmd("lastnews")
|
||||
mt.add_cmd("topnews")
|
||||
mt.add_cmd("paexport")
|
||||
console.print(text=mt.menu_text, menu="Portfolio - Brokers - Degiro")
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -489,3 +495,29 @@ class DegiroView:
|
||||
@log_start_end(log=logger)
|
||||
def __update_display_success():
|
||||
console.print("`Order` updated .")
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def transactions_export(self, ns_parser: Namespace):
|
||||
degiro_model = self.__degiro_model
|
||||
|
||||
portfolio_df = degiro_model.get_transactions_export(
|
||||
start=ns_parser.start.date(),
|
||||
end=ns_parser.end.date(),
|
||||
currency=ns_parser.currency,
|
||||
)
|
||||
|
||||
if portfolio_df is not None:
|
||||
print_rich_table(
|
||||
df=portfolio_df,
|
||||
headers=list(portfolio_df.columns),
|
||||
show_index=True,
|
||||
title="Degiro Transactions",
|
||||
)
|
||||
export_data(
|
||||
export_type=ns_parser.export,
|
||||
dir_path=str(Path(__file__).parent.parent.parent.absolute()),
|
||||
func_name="paexport",
|
||||
df=portfolio_df,
|
||||
)
|
||||
else:
|
||||
console.print("Error while fetching or processing Transactions.")
|
||||
|
||||
@@ -289,6 +289,15 @@ def test_call_func_expect_queue(expected_queue, func, queue):
|
||||
[],
|
||||
dict(),
|
||||
),
|
||||
(
|
||||
"call_paexport",
|
||||
[
|
||||
"--start=2022-01-01",
|
||||
],
|
||||
"DegiroView.transactions_export",
|
||||
[],
|
||||
dict(),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_call_func(
|
||||
|
||||
@@ -12,4 +12,5 @@
|
||||
companynews view news about a company with it's isin
|
||||
lastnews view latest news
|
||||
topnews view top news preview
|
||||
paexport csv export for portfolio analysis
|
||||
|
||||
|
||||
@@ -12,4 +12,5 @@
|
||||
companynews view news about a company with it's isin
|
||||
lastnews view latest news
|
||||
topnews view top news preview
|
||||
paexport csv export for portfolio analysis
|
||||
|
||||
|
||||
Reference in New Issue
Block a user