1###############################################################################
2#
3# ChartStock - A class for writing the Excel XLSX Stock charts.
4#
5# SPDX-License-Identifier: BSD-2-Clause
6#
7# Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org
8#
9
10from . import chart
11
12
13class ChartStock(chart.Chart):
14 """
15 A class for writing the Excel XLSX Stock charts.
16
17 """
18
19 ###########################################################################
20 #
21 # Public API.
22 #
23 ###########################################################################
24
25 def __init__(self):
26 """
27 Constructor.
28
29 """
30 super().__init__()
31
32 self.show_crosses = False
33 self.hi_low_lines = {}
34 self.date_category = True
35
36 # Override and reset the default axis values.
37 self.x_axis["defaults"]["num_format"] = "dd/mm/yyyy"
38 self.x2_axis["defaults"]["num_format"] = "dd/mm/yyyy"
39
40 # Set the available data label positions for this chart type.
41 self.label_position_default = "right"
42 self.label_positions = {
43 "center": "ctr",
44 "right": "r",
45 "left": "l",
46 "above": "t",
47 "below": "b",
48 # For backward compatibility.
49 "top": "t",
50 "bottom": "b",
51 }
52
53 self.set_x_axis({})
54 self.set_x2_axis({})
55
56 ###########################################################################
57 #
58 # Private API.
59 #
60 ###########################################################################
61
62 def _write_chart_type(self, args):
63 # Override the virtual superclass method with a chart specific method.
64 # Write the c:stockChart element.
65 self._write_stock_chart(args)
66
67 ###########################################################################
68 #
69 # XML methods.
70 #
71 ###########################################################################
72
73 def _write_stock_chart(self, args):
74 # Write the <c:stockChart> element.
75 # Overridden to add hi_low_lines().
76
77 if args["primary_axes"]:
78 series = self._get_primary_axes_series()
79 else:
80 series = self._get_secondary_axes_series()
81
82 if not series:
83 return
84
85 # Add default formatting to the series data.
86 self._modify_series_formatting()
87
88 self._xml_start_tag("c:stockChart")
89
90 # Write the series elements.
91 for data in series:
92 self._write_ser(data)
93
94 # Write the c:dropLines element.
95 self._write_drop_lines()
96
97 # Write the c:hiLowLines element.
98 if args.get("primary_axes"):
99 self._write_hi_low_lines()
100
101 # Write the c:upDownBars element.
102 self._write_up_down_bars()
103
104 # Write the c:axId elements
105 self._write_axis_ids(args)
106
107 self._xml_end_tag("c:stockChart")
108
109 def _modify_series_formatting(self):
110 # Add default formatting to the series data.
111
112 index = 0
113
114 for series in self.series:
115 if index % 4 != 3:
116 if not series["line"]["defined"]:
117 series["line"] = {"width": 2.25, "none": 1, "defined": 1}
118
119 if series["marker"] is None:
120 if index % 4 == 2:
121 series["marker"] = {"type": "dot", "size": 3}
122 else:
123 series["marker"] = {"type": "none"}
124
125 index += 1