|
1 | 1 | """ pyplots.ai |
2 | 2 | candlestick-basic: Basic Candlestick Chart |
3 | | -Library: altair 6.0.0 | Python 3.13.11 |
4 | | -Quality: 91/100 | Created: 2025-12-23 |
| 3 | +Library: altair 6.0.0 | Python 3.14.3 |
| 4 | +Quality: /100 | Updated: 2026-02-24 |
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import altair as alt |
|
12 | 12 | # Data - Simulated 30 days of stock price data |
13 | 13 | np.random.seed(42) |
14 | 14 | n_days = 30 |
15 | | -start_date = pd.Timestamp("2024-01-01") |
16 | | -dates = pd.date_range(start=start_date, periods=n_days, freq="B") # Business days |
| 15 | +dates = pd.date_range(start="2024-01-01", periods=n_days, freq="B") |
17 | 16 |
|
18 | 17 | # Generate realistic OHLC data with random walk |
19 | 18 | prices = [100.0] |
|
42 | 41 | ) |
43 | 42 |
|
44 | 43 | df = pd.DataFrame(data) |
| 44 | +df["direction"] = np.where(df["close"] >= df["open"], "Bullish", "Bearish") |
45 | 45 |
|
46 | | -# Add direction column for color encoding |
47 | | -df["direction"] = df.apply(lambda row: "Bullish" if row["close"] >= row["open"] else "Bearish", axis=1) |
48 | | - |
49 | | -# Color scale: green for bullish, red for bearish (most common convention) |
50 | | -color_scale = alt.Scale(domain=["Bullish", "Bearish"], range=["#26A69A", "#EF5350"]) |
| 46 | +# Colors - colorblind-safe: teal for bullish, warm orange for bearish |
| 47 | +color_scale = alt.Scale(domain=["Bullish", "Bearish"], range=["#26A69A", "#FF8F00"]) |
51 | 48 |
|
52 | 49 | # Candlestick wicks (high-low lines) |
53 | 50 | wicks = ( |
54 | 51 | alt.Chart(df) |
55 | | - .mark_rule(strokeWidth=3) |
| 52 | + .mark_rule(strokeWidth=1.5) |
56 | 53 | .encode( |
57 | | - x=alt.X("date:T", title="Date", axis=alt.Axis(labelFontSize=18, titleFontSize=22, format="%b %d")), |
58 | | - y=alt.Y( |
59 | | - "low:Q", title="Price ($)", scale=alt.Scale(zero=False), axis=alt.Axis(labelFontSize=18, titleFontSize=22) |
60 | | - ), |
| 54 | + x=alt.X("date:T", title="Date", axis=alt.Axis(format="%b %d")), |
| 55 | + y=alt.Y("low:Q", title="Price ($)", scale=alt.Scale(zero=False)), |
61 | 56 | y2="high:Q", |
62 | 57 | color=alt.Color("direction:N", scale=color_scale, legend=None), |
63 | 58 | ) |
|
66 | 61 | # Candlestick bodies (open-close bars) |
67 | 62 | bodies = ( |
68 | 63 | alt.Chart(df) |
69 | | - .mark_bar(size=24) |
| 64 | + .mark_bar(size=20) |
70 | 65 | .encode( |
71 | 66 | x="date:T", |
72 | 67 | y="open:Q", |
|
84 | 79 | ) |
85 | 80 | ) |
86 | 81 |
|
87 | | -# Layer wicks and bodies |
| 82 | +# Layer wicks and bodies with interactive zoom/pan |
88 | 83 | chart = ( |
89 | 84 | alt.layer(wicks, bodies) |
| 85 | + .resolve_scale(color="independent") |
90 | 86 | .properties( |
91 | | - width=1600, height=900, title=alt.Title("candlestick-basic · altair · pyplots.ai", fontSize=28, anchor="middle") |
| 87 | + width=1600, |
| 88 | + height=900, |
| 89 | + title=alt.Title("candlestick-basic \u00b7 altair \u00b7 pyplots.ai", fontSize=28, anchor="middle"), |
92 | 90 | ) |
93 | | - .configure_axis(labelFontSize=18, titleFontSize=22, gridOpacity=0.3) |
| 91 | + .configure_axis(labelFontSize=18, titleFontSize=22, gridOpacity=0.15) |
| 92 | + .configure_legend(labelFontSize=16, titleFontSize=18) |
94 | 93 | .configure_view(strokeWidth=0) |
| 94 | + .interactive() |
95 | 95 | ) |
96 | 96 |
|
97 | | -# Save as PNG and HTML |
| 97 | +# Save |
98 | 98 | chart.save("plot.png", scale_factor=3.0) |
99 | 99 | chart.save("plot.html") |
0 commit comments