GaiaEx AcademyGaiaEx Academy
Analiza danych z Pandas, NumPy, i Matplotlib
DeweloperProgramowanie12 min read

Analiza danych z Pandas, NumPy, i Matplotlib

Czyść, przekształcaj, i wizualizuj dane finansowe jak kwant

Udostępnij posty

NumPy: silnik pod maską

Każde poważne obliczenie finansowe w Pythonie ostatecznie przechodzi przez NumPy. Podczas gdy listy Pythona są elastyczne, są wolne — każdy element jest pełnym obiektem Pythona z narzutem sprawdzania typu. Tablice NumPy przechowują surowe liczby w ciągłych blokach pamięci, umożliwiając operacje, które działają 100 razy szybciej niż czyste pętle Pythona.

Tu jest różnica w praktyce:

import numpy as np

# Create an array of 1 million random daily returns
returns = np.random.normal(0.0005, 0.02, 1_000_000)

# Vectorized operations — no loops needed
cumulative = np.cumprod(1 + returns)  # Growth of $1
sharpe = returns.mean() / returns.std() * np.sqrt(252)
max_drawdown = np.min(cumulative / np.maximum.accumulate(cumulative) - 1)

print(f"Sharpe Ratio: {sharpe:.3f}")
print(f"Max Drawdown: {max_drawdown:.2%}")

Kluczowe koncepcje NumPy dla finansów:

  • Operacje wektoryzowane — zastosuj matematykę do całych tablic jednocześnie, zamiast pętli element po elemencie.
  • Broadcasting — automatycznie dopasowuje tablice różnych kształtów dla arytmetyki (np. odjęcie skalarnej średniej od każdego elementu).
  • Algebra liniowanp.linalg zapewnia mnożenie matrycowe, dekompozycję wartości własnych i solwery używane w optymalizacji portfela.
  • Losowe próbkowanie — symulacje Monte Carlo, próbkowanie bootstrap i modelowanie stochastyczne wszystkie opierają się na np.random.

Wskazówka wydajnościowa: zawsze preferuj wektoryzowane operacje NumPy ponad pętle for w Pythonie. Optymalizacja portfela na 500 aktywach, która zajmuje 30 sekund z pętlami, może zakończyć się w mniej niż 50 milisekundach z wektoryzowanym NumPy — 600-krotne przyspieszenie.

NumPy: contiguous memory + vectorized ops ndarray — dtype, shape, strides (C-contiguous) one loop in C/Fortran, not a million Python bytecode steps broadcasting: align shapes for element-wise math e.g. returns vector − scalar mean, or (n,) with (n, m) matrix rows linalg: cov, eig, solve — portfolio math lives here
Tablice to szybka ścieżka; broadcasting to sposób na zachowanie czytelnego kodu bez pętli.

Pandas: DataFrame dla danych finansowych

Jeśli NumPy jest silnikiem, pandas jest deską rozdzielczą. Owija tablice NumPy w oznakowane, indeksowane struktury, które czynią manipulację danymi finansowymi intuicyjną i wyrazistą.

Dwie podstawowe struktury to:

  • Series — pojedyncza kolumna danych z indeksem (myśl: szereg czasowy cen zamknięcia).
  • DataFrame — tabela kolumn, każda będąca Series, dzieląca wspólny indeks (myśl: dane świecowe OHLCV).

Wczytywanie i inspekcja danych jest prosta:

import pandas as pd

# Read from CSV
df = pd.read_csv("btc_daily.csv", parse_dates=["date"], index_col="date")

# Or from JSON (common in API responses)
df = pd.read_json("https://api.example.com/candles?symbol=ETH")

# Quick inspection
print(df.shape)          # (365, 5)
print(df.dtypes)         # Column types
print(df.describe())     # Statistical summary
print(df.tail())         # Last 5 rows

Co czyni pandas niezbędnym dla finansów, to jego DatetimeIndex. Kiedy twój indeks jest typu datetime, odblokowujesz potężne operacje na szeregach czasowych:

# Slice by date range
q1_data = df["2025-01":"2025-03"]

# Resample daily data to weekly OHLC
weekly = df["close"].resample("W").ohlc()

# Forward-fill missing data (weekends, holidays)
df = df.asfreq("D").ffill()

Te operacje obsługują chaotyczne realia danych finansowych — braki, różnice stref czasowych, nieregularne znaczniki czasu — więc możesz skupić się na analizie, a nie na hydraulice danych.

Obliczenia w okresie okna: średnie ruchowe i zmienność

Analiza finansowa jest z natury okienna (windowed). Rzadko interesuje cię pojedynczy punkt danych w izolacji — kontekst pochodzi z tego, jak odnosi się do niedawnej historii. Metoda .rolling() pandas jest twoim głównym narzędziem tutaj.

import pandas as pd
import numpy as np

# Assume df has a "close" column with DatetimeIndex
df["sma_20"] = df["close"].rolling(20).mean()
df["sma_50"] = df["close"].rolling(50).mean()
df["ema_12"] = df["close"].ewm(span=12).mean()

# Daily returns and rolling volatility
df["returns"] = df["close"].pct_change()
df["vol_30d"] = df["returns"].rolling(30).std() * np.sqrt(365)

# Bollinger Bands
df["bb_upper"] = df["sma_20"] + 2 * df["close"].rolling(20).std()
df["bb_lower"] = df["sma_20"] - 2 * df["close"].rolling(20).std()

# Rolling correlation between two assets
df["corr_btc_eth"] = df["btc_returns"].rolling(60).corr(df["eth_returns"])

Kluczowe obliczenia w oknie, które każdy trader powinien znać:

  • Prosta średnia ruchoma (SMA) — równo ważona średnia w N okresach. Opóźniona, ale stabilna.
  • Wykładnicza średnia ruchoma (EMA) — waży niedawne dane silniej przez .ewm(). Bardziej responsywna na zmiany cen.
  • Zmienność w oknie (rolling volatility) — odchylenie standardowe zwrotów w oknie, zannualizowane. Niezbędne do wielkości pozycji i budżetów ryzyka.
  • Korelacja w oknie (rolling correlation) — mierzy, jak dwa aktywa poruszają się razem w czasie. Kluczowe dla dywersyfikacji portfela.

Na platformach jak GaiaEx, możesz pobrać historyczne dane świecowe przez API handlowe, wczytać je do DataFrame pandas, i obliczyć te wskaźniki w sekundach — wszystko podczas gdy twoje aktywa pozostają bezpieczne w twoim portfelu MPC.

GroupBy i agregacja dla analizy portfela

Kiedy zarządzasz wielu aktywami, .groupby() staje się niezbędne. Pozwala rozdzielić dane po kategorii, zastosować obliczenia i połączyć wyniki — wzorzec podziel-zastosuj-połącz (split-apply-combine).

# DataFrame with multiple assets
trades = pd.DataFrame({
    "symbol": ["BTC", "ETH", "BTC", "SOL", "ETH", "BTC"],
    "side": ["buy", "buy", "sell", "buy", "sell", "buy"],
    "pnl": [120.5, -45.2, 89.0, 210.3, 55.8, -30.1],
    "volume": [5000, 3200, 4800, 1500, 2900, 5100],
})

# Performance by asset
summary = trades.groupby("symbol").agg(
    total_pnl=("pnl", "sum"),
    avg_pnl=("pnl", "mean"),
    trade_count=("pnl", "count"),
    total_volume=("volume", "sum"),
    win_rate=("pnl", lambda x: (x > 0).mean()),
)

print(summary.sort_values("total_pnl", ascending=False))

Zaawansowane wzorce agregacji dla pracy portfelowej:

  • Wielopoziomowy groupby — grupuj po symbolu i stronie, aby zobaczyć wyniki pozycji długich vs krótkich per aktywo.
  • Niestandardowe funkcje agregacji — oblicz wskaźniki Sharpe'a, wskaźniki Sortino, lub maksymalne obsunięcie kapitału (drawdown) per grupa aktywów.
  • Tabele przestawne (pivot tables) — przekształć dane, aby zobaczyć miesięczne zwroty per aktywo w formacie przyjaznym mapie ciepła, używając pd.pivot_table().
  • Resampling z groupby — połącz resampling oparty na czasie z grupowaniem kategorycznym dla analizy szeregów czasowych wielu aktywów.

Matplotlib: rysowanie akcji cenowej i sygnałów

Dane bez wizualizacji są tylko liczbami. Matplotlib przekształca twoją analizę w wykresy, które ujawniają wzorce niewidzialne w surowych danych.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

fig, axes = plt.subplots(3, 1, figsize=(14, 10),
                         sharex=True, gridspec_kw={"height_ratios": [3, 1, 1]})

# Price + Moving Averages
axes[0].plot(df.index, df["close"], label="Close", linewidth=1.2)
axes[0].plot(df.index, df["sma_20"], label="SMA 20", linestyle="--")
axes[0].fill_between(df.index, df["bb_upper"], df["bb_lower"],
                     alpha=0.1, color="blue", label="Bollinger Bands")
axes[0].set_ylabel("Price (USD)")
axes[0].legend(loc="upper left")

# Volume bars
colors = ["green" if c > o else "red"
          for c, o in zip(df["close"], df["open"])]
axes[1].bar(df.index, df["volume"], color=colors, alpha=0.7)
axes[1].set_ylabel("Volume")

# Rolling Volatility
axes[2].plot(df.index, df["vol_30d"], color="purple")
axes[2].set_ylabel("30d Volatility")
axes[2].axhline(y=0.8, color="red", linestyle=":", alpha=0.5)

axes[2].xaxis.set_major_formatter(mdates.DateFormatter("%b %Y"))
plt.tight_layout()
plt.savefig("analysis_dashboard.png", dpi=150)
plt.show()

To tworzy profesjonalny trzypanelowy dashboard: akcja cenowa ze wstęgami Bollingera na górze, wolumen w środku, i zmienność na dole. Ten układ odzwierciedla to, co widziałbyś na profesjonalnych terminalach handlowych.

Do wizualizacji statystycznej, seaborn budowany jest na Matplotlib z funkcjami wyższego poziomu:

import seaborn as sns

# Return distribution
sns.histplot(df["returns"].dropna(), bins=100, kde=True)

# Correlation heatmap across assets
corr_matrix = portfolio_returns.corr()
sns.heatmap(corr_matrix, annot=True, cmap="RdYlGn", center=0)
Pandas → analysis; Matplotlib → insight DataFrame index + columns rolling resample groupby Series metrics returns, vol, Sharpe matplotlib.pyplot — figure, axes, artists price volume indicators seaborn optional — same Artist layer, prettier defaults
Pandas przygotowuje uporządkowane tabele; Matplotlib mapuje je na osie, które możesz anotować i udostępniać.

Składanie wszystkiego razem: pełny pipeline analizy

Prawdziwa moc wyłania się, kiedy łączysz te narzędzia w powtarzalny pipeline. Tu jest workflow, który profesjonalni kwanci używają codziennie:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def analyze_asset(symbol: str, df: pd.DataFrame) -> dict:
    """Full analysis pipeline for a single asset."""
    df["returns"] = df["close"].pct_change()
    df["log_returns"] = np.log(df["close"] / df["close"].shift(1))

    return {
        "symbol": symbol,
        "total_return": (df["close"].iloc[-1] / df["close"].iloc[0]) - 1,
        "annual_vol": df["returns"].std() * np.sqrt(365),
        "sharpe": df["returns"].mean() / df["returns"].std() * np.sqrt(365),
        "max_drawdown": (df["close"] / df["close"].cummax() - 1).min(),
        "skewness": df["returns"].skew(),
        "kurtosis": df["returns"].kurtosis(),
    }

# Analyze multiple assets
results = [analyze_asset(sym, data) for sym, data in assets.items()]
summary = pd.DataFrame(results).set_index("symbol")
print(summary.round(4))

Ten pipeline przyjmuje surowe dane cenowe i produkuje wyczerpujący profil ryzyka-zwrotu dla każdego aktywa. Od tego miejsca możesz podać te metryki do optymalizatora portfela, generować rekomendacje alokacji, lub wyzwalać sygnały rebalansowania.

Stos pandas-NumPy-Matplotlib jest fundamentem, na którym opiera się wszystko inne w finansach Pythona. Opanuj te trzy biblioteki i będziesz mieć umiejętności do analizy każdego rynku, budowania każdego wskaźnika, i wizualizacji każdej strategii — czy handlujesz akcjami na NYSE, kryptowalutami na GaiaEx, czy instrumentami pochodnymi na CME.