【Amazon.co.jp限定】 バッファローWiFi ルーター無線LAN Wi-Fi 6 11ax / 11ac AX1800 573+1201Mbps 日本メーカー LANケーブル同梱 【 iPhone 16e / 16 / 15 / 14 / Nintendo Switch / PS5 動作確認済み 】 エコパッケージ WSR-1800AX4P/NBK
¥7,180 (2025-07-17 16:40 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)マウス Bluetooth 無線 【静音クリック&軽量設計|効率UPの5ボタン設計】 ワイヤレスマウス type-c 充電式 戻る 進むボタン搭載 軽量 静音 800/1200/1600/ 3段階DPI切替 5ボタン USB ワイヤレス ブルートゥース テレワーク ゲーミング 持ち運び ノートパソコン パソコン iPad pc Windows Mac対応 wireless mouse
¥1,580 (2025-07-17 16:40 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)沢口愛華 【増量版 全50P】ヤンマガアザーっす!<YM2025年19号未公開カット> ヤンマガデジタル写真集
¥1,210 (2025-07-17 16:40 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)前回の記事で基本的な価格表示ができるようになりました。今回は、プロのトレーダーが使うような美しいチャートを追加して、本格的な分析ツールに仕上げていきます。難しそうに見えますが、実は数行のコードで驚くほど高機能なチャートが作れるんです!
目次
Plotlyとは?なぜグラフライブラリの中で最強なのか
従来のグラフライブラリとの違い
Pythonでグラフを作る代表的なライブラリの比較:
Matplotlib(従来の定番):
import matplotlib.pyplot as plt
# 10行以上のコードでシンプルなグラフ
plt.figure(figsize=(10, 6))
plt.plot(dates, prices)
plt.title('Price Chart')
plt.xlabel('Date')
plt.ylabel('Price')
plt.show()
# しかも、インタラクティブ機能なし...
Plotly(最新の高機能):
import plotly.express as px
# 1行でインタラクティブなグラフ完成!
fig = px.line(df, x='date', y='price', title='Price Chart')
Plotlyの驚くべき機能
- ズーム・パン:マウスで自由に拡大・移動
- ホバー情報:グラフ上をマウスオーバーで詳細表示
- レスポンシブ:画面サイズに自動対応
- 美しいデザイン:デフォルトでプロ級の見た目
- アニメーション:データの変化を動的に表現
環境準備:Plotlyを追加インストール
pip install plotly
インストール確認
簡単なテストでPlotlyが動作するか確認しましょう:
# test_plotly.py
import streamlit as st
import plotly.express as px
import pandas as pd
st.title("📊 Plotly動作テスト")
# サンプルデータ作成
df = pd.DataFrame({
'x': [1, 2, 3, 4, 5],
'y': [2, 4, 1, 5, 3]
})
# グラフ作成
fig = px.line(df, x='x', y='y', title='テストグラフ')
# Streamlitで表示
st.plotly_chart(fig)
st.success("Plotlyが正常に動作しています!")
実行してインタラクティブなグラフが表示されれば成功です。
ローソク足チャートの作成
仮想通貨分析に欠かせないローソク足チャートを作ってみましょう:
# candlestick_chart.py
import streamlit as st
import ccxt
import pandas as pd
import plotly.graph_objects as go
from datetime import datetime
st.title("📈 ローソク足チャート")
# OHLCV データ取得関数
@st.cache_data(ttl=300) # 5分間キャッシュ
def get_ohlcv_data(symbol='BTC/USDT', timeframe='1h', limit=100):
"""
OHLCV(Open, High, Low, Close, Volume)データを取得
Args:
symbol: 通貨ペア(例:'BTC/USDT')
timeframe: 時間足(例:'1h', '1d')
limit: 取得する期間数
Returns:
DataFrame: 日時、始値、高値、安値、終値、出来高
"""
try:
exchange = ccxt.binance()
# OHLCVデータを取得
ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
# DataFrameに変換
df = pd.DataFrame(
ohlcv,
columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']
)
# タイムスタンプを日時に変換
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
return df
except Exception as e:
st.error(f"データ取得エラー: {e}")
return pd.DataFrame()
# サイドバーで設定
st.sidebar.header("📊 チャート設定")
# 通貨選択
symbol = st.sidebar.selectbox(
"通貨ペアを選択",
['BTC/USDT', 'ETH/USDT', 'XRP/USDT', 'ADA/USDT', 'DOT/USDT']
)
# 時間足選択
timeframe = st.sidebar.selectbox(
"時間足を選択",
['1m', '5m', '15m', '1h', '4h', '1d'],
index=3 # デフォルトは1h
)
# 表示期間
limit = st.sidebar.slider(
"表示期間(本数)",
min_value=50,
max_value=500,
value=100,
step=50
)
# データ取得
st.write(f"**{symbol}** のチャートを表示中...")
with st.spinner('データを取得中...'):
df = get_ohlcv_data(symbol, timeframe, limit)
if not df.empty:
# ローソク足チャート作成
fig = go.Figure(data=go.Candlestick(
x=df['timestamp'],
open=df['open'],
high=df['high'],
low=df['low'],
close=df['close'],
name=symbol
))
# レイアウト設定
fig.update_layout(
title=f"{symbol} ローソク足チャート ({timeframe})",
xaxis_title="日時",
yaxis_title="価格 (USDT)",
height=600,
xaxis_rangeslider_visible=False # 下部のスライダーを非表示
)
# チャートを表示
st.plotly_chart(fig, use_container_width=True)
# 統計情報表示
st.subheader("📊 統計情報")
col1, col2, col3, col4 = st.columns(4)
current_price = df['close'].iloc[-1]
price_change = current_price - df['close'].iloc[-2]
price_change_pct = (price_change / df['close'].iloc[-2]) * 100
with col1:
st.metric("現在価格", f"${current_price:,.2f}")
with col2:
st.metric(
"前回比",
f"${price_change:+,.2f}",
delta=f"{price_change_pct:+.2f}%"
)
with col3:
highest = df['high'].max()
st.metric("期間最高値", f"${highest:,.2f}")
with col4:
lowest = df['low'].min()
st.metric("期間最安値", f"${lowest:,.2f}")
else:
st.error("チャートデータを取得できませんでした")
出来高付きチャートで本格分析
価格と出来高を組み合わせた本格的な分析チャートを作成:
# advanced_chart.py
import streamlit as st
import ccxt
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
st.title("📊 高度なチャート分析")
@st.cache_data(ttl=300)
def get_detailed_data(symbol='BTC/USDT', timeframe='1h', limit=200):
"""詳細なOHLCVデータと移動平均線を取得"""
try:
exchange = ccxt.binance()
ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
df = pd.DataFrame(
ohlcv,
columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']
)
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
# 移動平均線を計算
df['sma_20'] = df['close'].rolling(window=20).mean() # 20期間移動平均
df['sma_50'] = df['close'].rolling(window=50).mean() # 50期間移動平均
return df
except Exception as e:
st.error(f"データ取得エラー: {e}")
return pd.DataFrame()
# 設定パネル
st.sidebar.header("🛠️ 詳細設定")
symbol = st.sidebar.selectbox(
"分析する通貨",
['BTC/USDT', 'ETH/USDT', 'XRP/USDT', 'ADA/USDT']
)
timeframe = st.sidebar.selectbox(
"時間足",
['1h', '4h', '1d'],
index=1
)
# 表示する要素の選択
show_volume = st.sidebar.checkbox("出来高を表示", True)
show_ma = st.sidebar.checkbox("移動平均線を表示", True)
# データ取得
df = get_detailed_data(symbol, timeframe)
if not df.empty:
# サブプロット作成(価格チャートと出来高チャート)
if show_volume:
fig = make_subplots(
rows=2, cols=1,
shared_xaxes=True,
vertical_spacing=0.1,
subplot_titles=(f'{symbol} 価格チャート', '出来高'),
row_width=[0.7, 0.3]
)
else:
fig = make_subplots(rows=1, cols=1)
# ローソク足チャート
fig.add_trace(
go.Candlestick(
x=df['timestamp'],
open=df['open'],
high=df['high'],
low=df['low'],
close=df['close'],
name="価格"
),
row=1, col=1
)
# 移動平均線
if show_ma:
# 20期間移動平均
fig.add_trace(
go.Scatter(
x=df['timestamp'],
y=df['sma_20'],
mode='lines',
name='20期間移動平均',
line=dict(color='orange', width=2)
),
row=1, col=1
)
# 50期間移動平均
fig.add_trace(
go.Scatter(
x=df['timestamp'],
y=df['sma_50'],
mode='lines',
name='50期間移動平均',
line=dict(color='blue', width=2)
),
row=1, col=1
)
# 出来高バーチャート
if show_volume:
# 価格が上昇した日は緑、下降した日は赤
colors = ['green' if close >= open else 'red'
for close, open in zip(df['close'], df['open'])]
fig.add_trace(
go.Bar(
x=df['timestamp'],
y=df['volume'],
name="出来高",
marker_color=colors,
opacity=0.7
),
row=2, col=1
)
# レイアウト設定
fig.update_layout(
title=f"{symbol} 詳細チャート ({timeframe})",
yaxis_title="価格 (USDT)",
height=800 if show_volume else 600,
xaxis_rangeslider_visible=False
)
if show_volume:
fig.update_yaxes(title_text="出来高", row=2, col=1)
# チャート表示
st.plotly_chart(fig, use_container_width=True)
# トレンド分析
st.subheader("🔍 トレンド分析")
# 最新の移動平均線の値
latest_price = df['close'].iloc[-1]
latest_sma20 = df['sma_20'].iloc[-1]
latest_sma50 = df['sma_50'].iloc[-1]
col1, col2 = st.columns(2)
with col1:
st.write("**短期トレンド(20期間移動平均):**")
if latest_price > latest_sma20:
st.success("🟢 上昇トレンド")
else:
st.error("🔴 下降トレンド")
with col2:
st.write("**中期トレンド(50期間移動平均):**")
if latest_price > latest_sma50:
st.success("🟢 上昇トレンド")
else:
st.error("🔴 下降トレンド")
# ゴールデンクロス・デッドクロス判定
if not pd.isna(latest_sma20) and not pd.isna(latest_sma50):
if latest_sma20 > latest_sma50:
st.info("✨ ゴールデンクロス状態(買いシグナル)")
else:
st.warning("💀 デッドクロス状態(売りシグナル)")
else:
st.error("データを取得できませんでした")
複数通貨の比較チャート
複数の仮想通貨を同時に比較できるチャートを作成:
# comparison_chart.py
import streamlit as st
import ccxt
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
st.title("⚖️ 複数通貨比較チャート")
@st.cache_data(ttl=300)
def get_comparison_data(symbols, timeframe='1d', limit=30):
"""複数通貨の比較データを取得"""
exchange = ccxt.binance()
all_data = []
for symbol in symbols:
try:
ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
df = pd.DataFrame(
ohlcv,
columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']
)
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df['symbol'] = symbol
# 正規化(最初の価格を100として相対変化率を計算)
first_price = df['close'].iloc[0]
df['normalized'] = (df['close'] / first_price) * 100
all_data.append(df)
except Exception as e:
st.warning(f"{symbol} のデータ取得に失敗: {e}")
if all_data:
return pd.concat(all_data, ignore_index=True)
else:
return pd.DataFrame()
# 比較する通貨を選択
st.sidebar.header("🔄 比較設定")
available_currencies = ['BTC/USDT', 'ETH/USDT', 'XRP/USDT', 'ADA/USDT', 'DOT/USDT', 'LINK/USDT']
selected_currencies = st.sidebar.multiselect(
"比較する通貨を選択(複数選択可)",
available_currencies,
default=['BTC/USDT', 'ETH/USDT']
)
timeframe = st.sidebar.selectbox(
"期間",
['1h', '4h', '1d', '1w'],
index=2
)
limit = st.sidebar.slider("表示期間", 7, 90, 30)
if selected_currencies:
# データ取得
comparison_df = get_comparison_data(selected_currencies, timeframe, limit)
if not comparison_df.empty:
# 正規化価格の比較チャート
st.subheader("📈 相対パフォーマンス比較")
st.caption("最初の時点を100として、そこからの変化率を表示")
fig_normalized = px.line(
comparison_df,
x='timestamp',
y='normalized',
color='symbol',
title="相対パフォーマンス(正規化)",
labels={'normalized': '相対価格 (基準=100)', 'timestamp': '日時'}
)
fig_normalized.update_layout(height=500)
st.plotly_chart(fig_normalized, use_container_width=True)
# 実際の価格比較(別々のスケール)
st.subheader("💰 実際の価格推移")
fig_actual = go.Figure()
for symbol in selected_currencies:
symbol_data = comparison_df[comparison_df['symbol'] == symbol]
fig_actual.add_trace(
go.Scatter(
x=symbol_data['timestamp'],
y=symbol_data['close'],
mode='lines',
name=symbol,
yaxis='y1' if symbol == selected_currencies[0] else 'y2'
)
)
# デュアル軸設定(2つの通貨のスケールが大きく異なる場合)
if len(selected_currencies) >= 2:
fig_actual.update_layout(
title="実際の価格推移(デュアル軸)",
xaxis_title="日時",
yaxis=dict(title=f"{selected_currencies[0]} 価格", side="left"),
yaxis2=dict(title=f"{selected_currencies[1]} 価格", side="right", overlaying="y"),
height=500
)
else:
fig_actual.update_layout(
title="実際の価格推移",
xaxis_title="日時",
yaxis_title="価格 (USDT)",
height=500
)
st.plotly_chart(fig_actual, use_container_width=True)
# パフォーマンス統計
st.subheader("📊 パフォーマンス統計")
stats_data = []
for symbol in selected_currencies:
symbol_data = comparison_df[comparison_df['symbol'] == symbol]
if len(symbol_data) > 1:
first_price = symbol_data['close'].iloc[0]
last_price = symbol_data['close'].iloc[-1]
total_return = ((last_price - first_price) / first_price) * 100
stats_data.append({
'通貨': symbol,
'開始価格': f"${first_price:,.2f}",
'最終価格': f"${last_price:,.2f}",
'リターン': f"{total_return:+.2f}%"
})
if stats_data:
stats_df = pd.DataFrame(stats_data)
st.dataframe(stats_df, use_container_width=True)
# 最高・最低パフォーマンス
returns = [float(stat['リターン'].replace('%', '').replace('+', ''))
for stat in stats_data]
best_idx = returns.index(max(returns))
worst_idx = returns.index(min(returns))
col1, col2 = st.columns(2)
with col1:
st.success(f"🏆 最高パフォーマンス: {stats_data[best_idx]['通貨']}")
with col2:
st.error(f"📉 最低パフォーマンス: {stats_data[worst_idx]['通貨']}")
else:
st.info("サイドバーから比較したい通貨を選択してください")
# 使い方ガイド
with st.expander("💡 チャートの見方・使い方"):
st.write("""
**相対パフォーマンス比較:**
- 全通貨を同じ基準(100)からスタートして比較
- どの通貨が最も成長したかが一目で分かる
- 線が上に行くほど良いパフォーマンス
**実際の価格推移:**
- 各通貨の実際の価格変動を表示
- 価格スケールが異なる場合はデュアル軸で表示
**チャートの操作方法:**
- 🔍 ドラッグで範囲選択してズーム
- 📱 ダブルクリックでズームリセット
- 👆 マウスオーバーで詳細データ表示
- 📱 凡例クリックで表示/非表示切り替え
""")
まとめ
この記事では以下の機能を実装しました:
🎯 実装した機能
- ローソク足チャート:プロトレーダー級の分析
- 移動平均線:トレンド分析機能
- 出来高表示:取引の活発さを可視化
- 複数通貨比較:相対パフォーマンス分析
- インタラクティブ操作:ズーム・ホバー情報
🔧 使用した技術
- Streamlit:Webアプリフレームワーク
- Plotly:高機能グラフライブラリ
- CCXT:仮想通貨データ取得
- Pandas:データ処理・分析
次回の第3部では、ポートフォリオ管理とアラート機能を追加して、完全な投資管理ツールに仕上げます。