File size: 4,198 Bytes
ce4bc73 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
"""
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."""
# Create sample data for testing
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."""
# Create chart
fig = create_pnl_chart(
self.pnl_data,
self.summary,
self.current_price,
self.ticker,
mode="default",
)
# Verify the chart is a Plotly figure
self.assertIsInstance(fig, go.Figure)
# Verify the chart has the correct number of traces
# 1 for combined P&L, 2 for individual positions, 3 for markers (max profit, max loss, current)
self.assertEqual(len(fig.data), 6)
# Verify the chart title contains the ticker
self.assertIn(self.ticker, fig.layout.title.text)
# Test with cost basis mode
fig_cost_basis = create_pnl_chart(
self.pnl_data,
self.summary,
self.current_price,
self.ticker,
mode="cost_basis",
)
# Verify the chart title contains the ticker
self.assertIn(self.ticker, fig_cost_basis.layout.title.text)
def test_create_pnl_summary(self):
"""Test creating a P&L summary component."""
# Create summary component
summary_component = create_pnl_summary(self.summary, mode="default")
# Verify the summary component is a Div
from dash import html
self.assertIsInstance(summary_component, html.Div)
# Verify the summary component contains the expected elements
self.assertIn("Max Profit", str(summary_component))
self.assertIn("Max Loss", str(summary_component))
self.assertIn("Break-even", str(summary_component))
# Test with cost basis mode (should be the same as default now)
summary_component_cost_basis = create_pnl_summary(
self.summary, mode="cost_basis"
)
# Verify the summary component contains the same elements
self.assertIn("Max Profit", str(summary_component_cost_basis))
def test_create_pnl_modal(self):
"""Test creating a P&L modal."""
# Create modal
modal = create_pnl_modal()
# Verify the modal has the correct ID
self.assertEqual(modal.id, "pnl-modal")
# Verify the modal contains the chart
self.assertIn("pnl-chart", str(modal))
# Verify the modal contains the summary section
self.assertIn("pnl-summary", str(modal))
if __name__ == "__main__":
unittest.main()
|