Skip to content

Commit

Permalink
[pre-commit.ci lite] apply automatic fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
pre-commit-ci-lite[bot] authored Jan 4, 2024
1 parent 84e064d commit 207b7e9
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 64 deletions.
2 changes: 1 addition & 1 deletion finalynx/analyzer/asset_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def analyzeTime(self, target_date: date) -> Dict[str, float]:
""":returns: A dictionary with keys as the asset class names and values as the
sum of investments corresponding to each class."""
return self._recursive_mergeTime(self.node, target_date)

def _recursive_mergeTime(self, node: Node, target_date: date) -> Dict[str, Any]:
"""Internal method for recursive searching."""
total = {c.value: 0.0 for c in AssetClass}
Expand Down
4 changes: 2 additions & 2 deletions finalynx/analyzer/envelopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def analyzeTime(self, target_date: date) -> Dict[str, float]:
""":returns: A dictionary with keys as the asset class names and values as the
sum of investments corresponding to each class."""
return self._recursive_mergeTime(self.node, target_date)

def _recursive_mergeTime(self, node: Node, target_date: date) -> Dict[str, Any]:
"""Internal method for recursive searching."""
total = {}
Expand All @@ -42,7 +42,7 @@ def _recursive_mergeTime(self, node: Node, target_date: date) -> Dict[str, Any]:
# Folders merge what the children return
elif isinstance(node, Folder):
for child in node.children:
for key, value in self._recursive_mergeTime(child,target_date).items():
for key, value in self._recursive_mergeTime(child, target_date).items():
if key in total.keys():
total[key] += value
else:
Expand Down
4 changes: 2 additions & 2 deletions finalynx/analyzer/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def analyzeTime(self, target_date: date) -> Dict[str, float]:
""":returns: A dictionary with keys as the asset class names and values as the
sum of investments corresponding to each class."""
return self._recursive_mergeTime(self.node, target_date)

def _recursive_mergeTime(self, node: Node, target_date: date) -> Dict[str, Any]:
"""Internal method for recursive searching."""
total = {}
Expand All @@ -35,7 +35,7 @@ def _recursive_mergeTime(self, node: Node, target_date: date) -> Dict[str, Any]:
# Folders merge what the children return
elif isinstance(node, Folder):
for child in node.children:
for key, value in self._recursive_mergeTime(child,target_date).items():
for key, value in self._recursive_mergeTime(child, target_date).items():
if key in total.keys():
total[key] += value
else:
Expand Down
4 changes: 2 additions & 2 deletions finalynx/analyzer/subasset_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class AnalyzeSubAssetClasses(Analyzer):
"DeFi": "#bdcf32",
# Passives
"Véhicule": "#434348",
"Passif": "#434348",
"Passif": "#434348",
# Exotics
"Forêts": "#228c83",
"Art": "#228c83",
Expand Down Expand Up @@ -112,7 +112,7 @@ def analyzeTime(self, target_date: date) -> Dict[str, float]:
""":returns: A dictionary with keys as the Sub asset class names and values as the
sum of investments corresponding to each class."""
return self._recursive_mergeTime(self.node, target_date)

def _recursive_mergeTime(self, node: Node, target_date: date) -> Dict[str, Any]:
"""Internal method for recursive searching."""
total = {}
Expand Down
10 changes: 5 additions & 5 deletions finalynx/assistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def __init__(
self.buckets = buckets if buckets else []
self.envelopes = envelopes if envelopes else []

#Storage for value of portfolio at each intermediate step
# Storage for value of portfolio at each intermediate step
self.intermediate_value = []

# Options that can either be set in the constructor or from the command line options, see --help
Expand Down Expand Up @@ -194,11 +194,11 @@ def _parse_args(self) -> None:
if args["--future"] and self.simulation:
self.simulation.print_final = True
if args["--each-step"] and self.simulation:
self.simulation.print_each_step = True
self.simulation.print_each_step = True
if args["--sim-steps"] and self.simulation:
self.simulation.step_years = int(args["--sim-steps"])
if args["--metric-frequency"] and self.simulation:
self.simulation.metrics_record_freqency = str(args["--metric-frequency"])
self.simulation.metrics_record_freqency = str(args["--metric-frequency"])
if args["--theme"]:
theme_name = str(args["--theme"])
if theme_name not in finalynx.theme.AVAILABLE_THEMES:
Expand Down Expand Up @@ -313,8 +313,8 @@ def append_worth(year: int, amount: float) -> None:
if (year - date.today().year) % self.simulation.step_years == 0:
append_worth(year, self.portfolio.get_amount())
if self.simulation.print_each_step:
#Storage for each intermediate simulation step
title = "Your portfolio in [bold]"+str(year)+"-12-31:[/]"
# Storage for each intermediate simulation step
title = "Your portfolio in [bold]" + str(year) + "-12-31:[/]"
self.intermediate_value.append(Panel(self.render_mainframe(), title=title))

# Run until the end date and append the final result
Expand Down
58 changes: 47 additions & 11 deletions finalynx/dashboard/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,53 @@ def _on_select_color_map(data: Any) -> None:
)
with ui.row():
self.chart_envelopes = ui.chart(AnalyzeEnvelopes(self.selected_node).chart())
self.chart_etats_enveloppes = ui.chart(timeline.chartOnTimeline("Evolution des états d'enveloppes",timeline._log_env_states,{
"Unknown": "#434348",
"Closed": "#999999",
"Locked": "#F94144",
"Taxed": "#F9C74F",
"Free": "#7BB151",
}) if timeline else {})
self.chart_enveloppes = ui.chart(timeline.chartOnTimeline("Evolution des enveloppes",timeline._log_enveloppe_values) if timeline else {})
self.chart_asset_classes = ui.chart(timeline.chartOnTimeline("Evolution des classes d'actifs",timeline._log_assets_classes_values,AnalyzeAssetClasses.ASSET_COLORS_FINARY) if timeline else {})
self.chart_subasset_classes = ui.chart(timeline.chartOnTimeline("Evolution des sous-classes d'actifs",timeline._log_assets_subclasses_values,AnalyzeSubAssetClasses.SUBASSET_COLORS_FINARY) if timeline else {})
self.chart_lines = ui.chart(timeline.chartOnTimeline("Evolution des lignes du portefeuille", timeline._log_lines_values, visible_by_default=False) if timeline else {})
self.chart_etats_enveloppes = ui.chart(
timeline.chartOnTimeline(
"Evolution des états d'enveloppes",
timeline._log_env_states,
{
"Unknown": "#434348",
"Closed": "#999999",
"Locked": "#F94144",
"Taxed": "#F9C74F",
"Free": "#7BB151",
},
)
if timeline
else {}
)
self.chart_enveloppes = ui.chart(
timeline.chartOnTimeline("Evolution des enveloppes", timeline._log_enveloppe_values)
if timeline
else {}
)
self.chart_asset_classes = ui.chart(
timeline.chartOnTimeline(
"Evolution des classes d'actifs",
timeline._log_assets_classes_values,
AnalyzeAssetClasses.ASSET_COLORS_FINARY,
)
if timeline
else {}
)
self.chart_subasset_classes = ui.chart(
timeline.chartOnTimeline(
"Evolution des sous-classes d'actifs",
timeline._log_assets_subclasses_values,
AnalyzeSubAssetClasses.SUBASSET_COLORS_FINARY,
)
if timeline
else {}
)
self.chart_lines = ui.chart(
timeline.chartOnTimeline(
"Evolution des lignes du portefeuille",
timeline._log_lines_values,
visible_by_default=False,
)
if timeline
else {}
)

ui.run(
title="Finalynx Dashboard",
Expand Down
107 changes: 67 additions & 40 deletions finalynx/simulator/timeline.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from dataclasses import dataclass
from datetime import date, datetime
from datetime import date
from datetime import datetime
from datetime import timedelta
from typing import Any
from typing import Dict
from typing import List
from typing import Optional

from finalynx.analyzer.asset_class import AnalyzeAssetClasses
from finalynx.analyzer.envelopes import AnalyzeEnvelopes
from finalynx.analyzer.lines import AnalyzeLines

from finalynx.analyzer.investment_state import AnalyzeInvestmentStates
from finalynx.analyzer.lines import AnalyzeLines
from finalynx.analyzer.subasset_class import AnalyzeSubAssetClasses
from finalynx.portfolio.bucket import Bucket
from finalynx.portfolio.constants import AssetClass
Expand Down Expand Up @@ -42,13 +43,14 @@ class Simulation:

# Whether to print the portfolio state in the console on each step of the simulation
print_each_step: bool = False

# Display the portfolio's worth in the console every `step` years
step_years: int = 5

# Record the portfolio stats on each day of the simulation 'DAY', 'MONTH', 'YEAR'
metrics_record_freqency: str = "MONTH"


class Timeline:
"""Main simulation engine to execute programmed actions on your portfolio."""

Expand Down Expand Up @@ -105,7 +107,7 @@ def step_until(self, target_date: date) -> None:
"""Execute all events until the specified date is reached."""
assert self.current_date < target_date, "Target date must be in the future."

#Enregistrement de la situation de démarrage du Portefeuille
# Enregistrement de la situation de démarrage du Portefeuille
self._record_metrics()

while self.current_date < target_date and not self.is_finished:
Expand All @@ -129,7 +131,7 @@ def step(self) -> bool:
if next_event.planned_date in self._log_events:
self._log_events[next_event.planned_date].append(next_event.name)
else:
self._log_events[next_event.planned_date]=[next_event.name]
self._log_events[next_event.planned_date] = [next_event.name]

# Recalculate the amounts for shared folders
for bucket in self._buckets:
Expand All @@ -142,9 +144,19 @@ def step(self) -> bool:
self._sort_events()

# Record the metrics if the year changed
#if next_event.planned_date.year != self.current_date.year:
# if next_event.planned_date.year != self.current_date.year:
# self._record_metrics()
if (self.simulation.metrics_record_freqency == "DAY" and next_event.planned_date != self.current_date) or (self.simulation.metrics_record_freqency == "YEAR" and next_event.planned_date.year != self.current_date.year) or (self.simulation.metrics_record_freqency == "MONTH" and next_event.planned_date.month != self.current_date.month):
if (
(self.simulation.metrics_record_freqency == "DAY" and next_event.planned_date != self.current_date)
or (
self.simulation.metrics_record_freqency == "YEAR"
and next_event.planned_date.year != self.current_date.year
)
or (
self.simulation.metrics_record_freqency == "MONTH"
and next_event.planned_date.month != self.current_date.month
)
):
self.current_date = next_event.planned_date
self._record_metrics()

Expand Down Expand Up @@ -179,52 +191,66 @@ def _record_metrics(self) -> None:
if key in self._log_enveloppe_values:
self._log_enveloppe_values[key].append(value)
else:
self._log_enveloppe_values[key]=[value]
self._log_enveloppe_values[key] = [value]

for key, value in AnalyzeAssetClasses(self._portfolio).analyzeTime(self.current_date).items():
self._log_assets_classes_values[key].append(value)

for key, value in AnalyzeSubAssetClasses(self._portfolio).analyzeTime(self.current_date).items():
if key in self._log_assets_subclasses_values:
self._log_assets_subclasses_values[key].append(value)
else:
self._log_assets_subclasses_values[key]=[value]
self._log_assets_subclasses_values[key] = [value]

for key, value in AnalyzeLines(self._portfolio).analyzeTime(self.current_date).items():
if key in self._log_lines_values:
self._log_lines_values[key].append(value)
else:
self._log_lines_values[key]=[value]
self._log_lines_values[key] = [value]
else:
#On doit remplacer les valeurs stockées par les nouvelles sans créer 2 fois l'enregistrement
# On doit remplacer les valeurs stockées par les nouvelles sans créer 2 fois l'enregistrement
ident = self._log_dates.index(self.current_date)
# Record the envelope states and their amounts at this date
for key, value in AnalyzeInvestmentStates(self._portfolio).analyze(self.current_date).items():
self._log_env_states[key][-1]=value
self._log_env_states[key][-1] = value
for key, value in AnalyzeEnvelopes(self._portfolio).analyzeTime(self.current_date).items():
if key in self._log_enveloppe_values:
self._log_enveloppe_values[key][-1]=value
self._log_enveloppe_values[key][-1] = value
else:
self._log_enveloppe_values[key]=[value]
self._log_enveloppe_values[key] = [value]
for key, value in AnalyzeAssetClasses(self._portfolio).analyzeTime(self.current_date).items():
self._log_assets_classes_values[key][-1]=value
self._log_assets_classes_values[key][-1] = value
for key, value in AnalyzeSubAssetClasses(self._portfolio).analyzeTime(self.current_date).items():
if key in self._log_assets_subclasses_values:
self._log_assets_subclasses_values[key][-1]=value
self._log_assets_subclasses_values[key][-1] = value
else:
self._log_assets_subclasses_values[key]=[value]
self._log_assets_subclasses_values[key] = [value]
for key, value in AnalyzeLines(self._portfolio).analyzeTime(self.current_date).items():
if key in self._log_lines_values:
self._log_lines_values[key][-1]=value
self._log_lines_values[key][-1] = value
else:
self._log_lines_values[key]=[value]

def chartOnTimeline(self, title: str, valuesToGraph: Dict[str, List[float]], colors: Dict[str,str]={}, visible_by_default: bool = True) -> Dict[str, Any]:
self._log_lines_values[key] = [value]

def chartOnTimeline(
self,
title: str,
valuesToGraph: Dict[str, List[float]],
colors: Dict[str, str] = {},
visible_by_default: bool = True,
) -> Dict[str, Any]:
"""Plot a Highcharts chart of the portfolio's caracteristics and amounts over time."""
#assert self._log_enveloppe_values, "Run the simulation before charting."
# assert self._log_enveloppe_values, "Run the simulation before charting."

return {
"chart": {"plotBackgroundColor": None, "plotBorderWidth": None, "plotShadow": False, "type": "area", "zooming": {"type": 'xy' }, "height":1200, "width":1000},
"chart": {
"plotBackgroundColor": None,
"plotBorderWidth": None,
"plotShadow": False,
"type": "area",
"zooming": {"type": "xy"},
"height": 1200,
"width": 1000,
},
"title": {"text": title, "align": "center"},
"plotOptions": {
"area": {
Expand All @@ -239,35 +265,36 @@ def chartOnTimeline(self, title: str, valuesToGraph: Dict[str, List[float]], col
"name": key,
"data": self.convertDataSeries(value),
"visible": visible_by_default,
"color": colors[key] if (key in colors) else {None}
"color": colors[key] if (key in colors) else {None},
}
for key, value in valuesToGraph.items()
],
"xAxis": {"type": 'datetime'},
"xAxis": {"type": "datetime"},
"yAxis": {"crosshair": True},
"tooltip": {
"xDateFormat": '%m %Y',
"pointFormat": '{point.x:%e/%m/%Y}: <b>{point.y:,.0f}€</b><br>',
"footerFormat": '<i>{series.name}</i>',
"xDateFormat": "%m %Y",
"pointFormat": "{point.x:%e/%m/%Y}: <b>{point.y:,.0f}€</b><br>",
"footerFormat": "<i>{series.name}</i>",
},
"credits": {"enabled": False},
}

def convertDataSeries(self, data: [float])->[Any]:
def convertDataSeries(self, data: [float]) -> [Any]:
"""Convert DataSeries in a time series format to allow non regular data"""
res=[]
res = []
i = 0
while i < len(data):
if (self._log_dates[i] in self._log_events):
evenements = "* "+"<br>* ".join(self._log_events[self._log_dates[i]])
else:
if self._log_dates[i] in self._log_events:
evenements = "* " + "<br>* ".join(self._log_events[self._log_dates[i]])
else:
evenements = ""
point = {"x": datetime.combine(self._log_dates[i], datetime.min.time()).timestamp() * 1000,
"y": data[i],
"name": evenements
}
point = {
"x": datetime.combine(self._log_dates[i], datetime.min.time()).timestamp() * 1000,
"y": data[i],
"name": evenements,
}
res.append(point)
i+=1
i += 1
return res

def _sort_events(self) -> None:
Expand Down
Loading

0 comments on commit 207b7e9

Please sign in to comment.