|
|
""" |
|
|
Unit tests for the P&L chart component. |
|
|
""" |
|
|
|
|
|
import unittest |
|
|
|
|
|
import plotly.graph_objects as go |
|
|
|
|
|
from src.folio.components.pnl_chart import ( |
|
|
create_pnl_chart, |
|
|
create_pnl_modal, |
|
|
create_pnl_summary, |
|
|
) |
|
|
|
|
|
|
|
|
class TestPnlChart(unittest.TestCase): |
|
|
"""Test cases for the P&L chart component.""" |
|
|
|
|
|
def setUp(self): |
|
|
"""Set up test fixtures.""" |
|
|
|
|
|
self.pnl_data = { |
|
|
"price_points": [90.0, 100.0, 110.0], |
|
|
"pnl_values": [-1000.0, 0.0, 1000.0], |
|
|
"individual_pnls": [ |
|
|
{ |
|
|
"price_points": [90.0, 100.0, 110.0], |
|
|
"pnl_values": [-1000.0, 0.0, 1000.0], |
|
|
"position": { |
|
|
"ticker": "SPY", |
|
|
"position_type": "stock", |
|
|
"quantity": 100, |
|
|
"price": 100.0, |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
"price_points": [90.0, 100.0, 110.0], |
|
|
"pnl_values": [200.0, 0.0, -200.0], |
|
|
"position": { |
|
|
"ticker": "SPY", |
|
|
"position_type": "option", |
|
|
"option_type": "PUT", |
|
|
"strike": 95.0, |
|
|
"quantity": -1, |
|
|
"price": 5.0, |
|
|
}, |
|
|
}, |
|
|
], |
|
|
} |
|
|
|
|
|
self.summary = { |
|
|
"current_pnl": 0.0, |
|
|
"max_profit": 1000.0, |
|
|
"max_profit_price": 110.0, |
|
|
"max_loss": -1000.0, |
|
|
"max_loss_price": 90.0, |
|
|
"breakeven_points": [100.0], |
|
|
} |
|
|
|
|
|
self.current_price = 100.0 |
|
|
self.ticker = "SPY" |
|
|
|
|
|
def test_create_pnl_chart(self): |
|
|
"""Test creating a P&L chart.""" |
|
|
|
|
|
fig = create_pnl_chart( |
|
|
self.pnl_data, |
|
|
self.summary, |
|
|
self.current_price, |
|
|
self.ticker, |
|
|
mode="default", |
|
|
) |
|
|
|
|
|
|
|
|
self.assertIsInstance(fig, go.Figure) |
|
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(fig.data), 6) |
|
|
|
|
|
|
|
|
self.assertIn(self.ticker, fig.layout.title.text) |
|
|
|
|
|
|
|
|
fig_cost_basis = create_pnl_chart( |
|
|
self.pnl_data, |
|
|
self.summary, |
|
|
self.current_price, |
|
|
self.ticker, |
|
|
mode="cost_basis", |
|
|
) |
|
|
|
|
|
|
|
|
self.assertIn(self.ticker, fig_cost_basis.layout.title.text) |
|
|
|
|
|
def test_create_pnl_summary(self): |
|
|
"""Test creating a P&L summary component.""" |
|
|
|
|
|
summary_component = create_pnl_summary(self.summary, mode="default") |
|
|
|
|
|
|
|
|
from dash import html |
|
|
|
|
|
self.assertIsInstance(summary_component, html.Div) |
|
|
|
|
|
|
|
|
self.assertIn("Max Profit", str(summary_component)) |
|
|
self.assertIn("Max Loss", str(summary_component)) |
|
|
self.assertIn("Break-even", str(summary_component)) |
|
|
|
|
|
|
|
|
summary_component_cost_basis = create_pnl_summary( |
|
|
self.summary, mode="cost_basis" |
|
|
) |
|
|
|
|
|
|
|
|
self.assertIn("Max Profit", str(summary_component_cost_basis)) |
|
|
|
|
|
def test_create_pnl_modal(self): |
|
|
"""Test creating a P&L modal.""" |
|
|
|
|
|
modal = create_pnl_modal() |
|
|
|
|
|
|
|
|
self.assertEqual(modal.id, "pnl-modal") |
|
|
|
|
|
|
|
|
self.assertIn("pnl-chart", str(modal)) |
|
|
|
|
|
|
|
|
self.assertIn("pnl-summary", str(modal)) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
unittest.main() |
|
|
|