Skip to content

Commit 9662db5

Browse files
feat(matplotlib): implement ohlc-bar (#7056)
## Implementation: `ohlc-bar` - python/matplotlib Implements the **python/matplotlib** version of `ohlc-bar`. **File:** `plots/ohlc-bar/implementations/python/matplotlib.py` **Parent Issue:** #3293 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25988388092)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 805f272 commit 9662db5

2 files changed

Lines changed: 193 additions & 139 deletions

File tree

plots/ohlc-bar/implementations/python/matplotlib.py

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
ohlc-bar: OHLC Bar Chart
3-
Library: matplotlib 3.10.8 | Python 3.13.11
4-
Quality: 93/100 | Created: 2026-01-08
3+
Library: matplotlib 3.10.9 | Python 3.13.13
4+
Quality: 91/100 | Updated: 2026-05-17
55
"""
66

7+
import os
8+
79
import matplotlib.dates as mdates
810
import matplotlib.pyplot as plt
911
import numpy as np
1012
import pandas as pd
1113
from matplotlib.lines import Line2D
1214

1315

16+
# Theme tokens
17+
THEME = os.getenv("ANYPLOT_THEME", "light")
18+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
19+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
20+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
21+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
22+
23+
# Okabe-Ito palette
24+
COLOR_UP = "#009E73" # Brand green for up bars
25+
COLOR_DOWN = "#D55E00" # Vermillion for down bars
26+
1427
# Data - Generate 45 trading days of synthetic stock OHLC data
1528
np.random.seed(42)
1629
n_days = 45
@@ -40,7 +53,8 @@
4053
df = pd.DataFrame({"date": dates, "open": open_prices, "high": high_prices, "low": low_prices, "close": close_prices})
4154

4255
# Plot
43-
fig, ax = plt.subplots(figsize=(16, 9))
56+
fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)
57+
ax.set_facecolor(PAGE_BG)
4458

4559
# Draw OHLC bars
4660
tick_width = 0.4 # Width of open/close ticks in days
@@ -50,10 +64,7 @@
5064
date_num = mdates.date2num(row["date"])
5165

5266
# Determine color based on price direction
53-
if row["close"] >= row["open"]:
54-
color = "#306998" # Python Blue for up bars
55-
else:
56-
color = "#D62728" # Red for down bars
67+
color = COLOR_UP if row["close"] >= row["open"] else COLOR_DOWN
5768

5869
# Draw high-low vertical line
5970
ax.plot([date_num, date_num], [row["low"], row["high"]], color=color, linewidth=line_width, solid_capstyle="round")
@@ -76,21 +87,27 @@
7687
solid_capstyle="butt",
7788
)
7889

79-
# Styling
80-
ax.set_xlabel("Date", fontsize=20)
81-
ax.set_ylabel("Price (USD)", fontsize=20)
82-
ax.set_title("ohlc-bar · matplotlib · pyplots.ai", fontsize=24)
83-
ax.tick_params(axis="both", labelsize=16)
90+
# Style
91+
ax.set_xlabel("Date", fontsize=20, color=INK)
92+
ax.set_ylabel("Price (USD)", fontsize=20, color=INK)
93+
ax.set_title("ohlc-bar · matplotlib · anyplot.ai", fontsize=24, fontweight="medium", color=INK)
94+
ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT)
8495

8596
# Format x-axis dates
8697
ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MONDAY))
8798
ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %d"))
8899
ax.xaxis.set_minor_locator(mdates.DayLocator())
89100
fig.autofmt_xdate(rotation=45)
90101

102+
# Spine styling
103+
for spine in ("top", "right"):
104+
ax.spines[spine].set_visible(False)
105+
for spine in ("left", "bottom"):
106+
ax.spines[spine].set_color(INK_SOFT)
107+
91108
# Grid for reading price levels
92-
ax.grid(True, alpha=0.3, linestyle="--", axis="y")
93-
ax.grid(True, alpha=0.15, linestyle="--", axis="x")
109+
ax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)
110+
ax.xaxis.grid(True, alpha=0.08, linewidth=0.8, color=INK)
94111

95112
# Add padding to y-axis
96113
y_min, y_max = ax.get_ylim()
@@ -99,10 +116,14 @@
99116

100117
# Add legend for up/down bars
101118
legend_elements = [
102-
Line2D([0], [0], color="#306998", linewidth=3, label="Up (Close ≥ Open)"),
103-
Line2D([0], [0], color="#D62728", linewidth=3, label="Down (Close < Open)"),
119+
Line2D([0], [0], color=COLOR_UP, linewidth=3, label="Up (Close ≥ Open)"),
120+
Line2D([0], [0], color=COLOR_DOWN, linewidth=3, label="Down (Close < Open)"),
104121
]
105-
ax.legend(handles=legend_elements, fontsize=16, loc="upper left")
122+
legend = ax.legend(handles=legend_elements, fontsize=16, loc="upper left")
123+
legend.get_frame().set_facecolor(ELEVATED_BG)
124+
legend.get_frame().set_edgecolor(INK_SOFT)
125+
for text in legend.get_texts():
126+
text.set_color(INK_SOFT)
106127

107128
plt.tight_layout()
108-
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
129+
plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG)

0 commit comments

Comments
 (0)