Remove weekend gaps from candlestick charts

- Use index positions instead of datetime for x-axis
- All candles now evenly spaced (no gaps for weekends/holidays)
- Date labels still show actual dates at regular intervals
- Updated example chart to reflect changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Simard
2025-12-26 12:17:40 -06:00
parent 7d88edb6e7
commit 8792c03e64
2 changed files with 30 additions and 17 deletions

View File

@@ -39,29 +39,37 @@ class ChartGenerator:
fig, ax = plt.subplots(figsize=(12, 6), facecolor='#1e1e1e') fig, ax = plt.subplots(figsize=(12, 6), facecolor='#1e1e1e')
ax.set_facecolor('#2d2d2d') ax.set_facecolor('#2d2d2d')
# Use index positions to remove weekend gaps
x_pos = list(range(len(closes)))
# Plot closing prices # Plot closing prices
ax.plot(dates, closes, color='#00d4ff', linewidth=2) ax.plot(x_pos, closes, color='#00d4ff', linewidth=2)
# Fill area under the line # Fill area under the line
ax.fill_between(dates, closes, alpha=0.3, color='#00d4ff') ax.fill_between(x_pos, closes, alpha=0.3, color='#00d4ff')
# Format x-axis (detect if intraday or multi-day) # Format x-axis with date labels (removing gaps)
if len(dates) > 0: if len(dates) > 0:
# Check if all data is from the same day # Check if all data is from the same day
first_date = dates[0].date() first_date = dates[0].date()
last_date = dates[-1].date() last_date = dates[-1].date()
is_intraday = first_date == last_date is_intraday = first_date == last_date
# Select tick positions (show ~7-10 labels)
tick_spacing = max(1, len(dates) // 7)
tick_indices = list(range(0, len(dates), tick_spacing))
if tick_indices[-1] != len(dates) - 1:
tick_indices.append(len(dates) - 1)
if is_intraday: if is_intraday:
# Show time for intraday data # Show time for intraday data
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M')) tick_labels = [dates[i].strftime('%H:%M') for i in tick_indices]
ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))
else: else:
# Show date for multi-day data # Show date for multi-day data
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d')) tick_labels = [dates[i].strftime('%m/%d') for i in tick_indices]
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
plt.xticks(rotation=45, ha='right') ax.set_xticks(tick_indices)
ax.set_xticklabels(tick_labels, rotation=45, ha='right')
# Grid styling # Grid styling
ax.grid(True, alpha=0.2, color='#ffffff', linestyle='-', linewidth=0.5) ax.grid(True, alpha=0.2, color='#ffffff', linestyle='-', linewidth=0.5)
@@ -126,35 +134,40 @@ class ChartGenerator:
# Calculate bar width # Calculate bar width
width = 0.6 width = 0.6
# Plot candlesticks # Plot candlesticks using index positions (removes weekend gaps)
for i in range(len(dates)): for i in range(len(dates)):
color = '#00ff88' if closes[i] >= opens[i] else '#ff4444' color = '#00ff88' if closes[i] >= opens[i] else '#ff4444'
# High-low line # High-low line
ax.plot([dates[i], dates[i]], [lows[i], highs[i]], color=color, linewidth=1) ax.plot([i, i], [lows[i], highs[i]], color=color, linewidth=1)
# Open-close rectangle # Open-close rectangle
height = abs(closes[i] - opens[i]) height = abs(closes[i] - opens[i])
bottom = min(opens[i], closes[i]) bottom = min(opens[i], closes[i])
ax.bar(dates[i], height, width, bottom=bottom, color=color, alpha=0.8) ax.bar(i, height, width, bottom=bottom, color=color, alpha=0.8)
# Format x-axis (detect if intraday or multi-day) # Format x-axis with date labels (removing gaps)
if len(dates) > 0: if len(dates) > 0:
# Check if all data is from the same day # Check if all data is from the same day
first_date = dates[0].date() first_date = dates[0].date()
last_date = dates[-1].date() last_date = dates[-1].date()
is_intraday = first_date == last_date is_intraday = first_date == last_date
# Select tick positions (show ~7-10 labels)
tick_spacing = max(1, len(dates) // 7)
tick_indices = list(range(0, len(dates), tick_spacing))
if tick_indices[-1] != len(dates) - 1:
tick_indices.append(len(dates) - 1)
if is_intraday: if is_intraday:
# Show time for intraday data # Show time for intraday data
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M')) tick_labels = [dates[i].strftime('%H:%M') for i in tick_indices]
ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))
else: else:
# Show date for multi-day data # Show date for multi-day data
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d')) tick_labels = [dates[i].strftime('%m/%d') for i in tick_indices]
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
plt.xticks(rotation=45, ha='right') ax.set_xticks(tick_indices)
ax.set_xticklabels(tick_labels, rotation=45, ha='right')
# Grid styling # Grid styling
ax.grid(True, alpha=0.2, color='#ffffff', linestyle='-', linewidth=0.5) ax.grid(True, alpha=0.2, color='#ffffff', linestyle='-', linewidth=0.5)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 20 KiB