Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import pandas as pd
- import matplotlib.pyplot as plt
- import mplfinance as mpf
- RANDOM_SEED = 42
- N = 70
- A = 3
- B = 0.2
- C = 2
- D = 0.5
- F = 0.5
- G = 0.07
- SEASON_FREQ = 0.5236
- HIST_FILE = "DIXY_160101_161201.txt"
- WINDOW_NOISE = 3
- WINDOW_SEASON = 12
- def generate_dynamic_series(
- n: int = N,
- a: float = A,
- b: float = B,
- c: float = C,
- d: float = D,
- f: float = F,
- g: float = G,
- season_freq: float = SEASON_FREQ,
- random_seed: int = RANDOM_SEED,
- ) -> pd.DataFrame:
- np.random.seed(random_seed)
- t = np.arange(1, n + 1)
- T = a + b * t
- season_raw = np.sin(np.sin(season_freq * t))
- S_add = c * season_raw
- E_add = d * np.random.normal(loc=0.0, scale=1.0, size=n)
- y_add = T + S_add + E_add
- S_mult = 1 + f * season_raw
- E_mult = 1 + g * np.random.normal(loc=0.0, scale=1.0, size=n)
- y_mult = T * S_mult * E_mult
- df = pd.DataFrame(
- {
- "t": t,
- "T": T,
- "S_add": S_add,
- "E_add": E_add,
- "y_add": y_add,
- "S_mult": S_mult,
- "E_mult": E_mult,
- "y_mult": y_mult,
- }
- )
- return df
- def plot_dynamic_series(df: pd.DataFrame) -> None:
- plt.figure(figsize=(10, 5))
- plt.plot(df["t"], df["y_add"], label="y_add (адитивна модель)")
- plt.title("Ряд динаміки (адитивна модель)")
- plt.xlabel("t, міс.")
- plt.ylabel("y_add")
- plt.grid(True)
- plt.legend()
- plt.tight_layout()
- plt.show()
- plt.figure(figsize=(10, 5))
- plt.plot(df["t"], df["y_mult"], label="y_mult (мультиплікативна модель)", color="orange")
- plt.title("Ряд динаміки (мультиплікативна модель)")
- plt.xlabel("t, міс.")
- plt.ylabel("y_mult")
- plt.grid(True)
- plt.legend()
- plt.tight_layout()
- plt.show()
- def load_historical_data(filename: str = HIST_FILE) -> pd.DataFrame:
- df = pd.read_csv(
- filename,
- sep=",",
- header=0,
- names=["TICKER", "PER", "DATE", "TIME", "OPEN", "HIGH", "LOW", "CLOSE", "VOL"],
- )
- df["DATE"] = pd.to_datetime(df["DATE"], format="%d/%m/%y", dayfirst=True)
- df = df.sort_values("DATE").set_index("DATE")
- return df
- def plot_close_prices(df_hist: pd.DataFrame) -> None:
- plt.figure(figsize=(10, 5))
- plt.plot(df_hist.index, df_hist["CLOSE"], label="CLOSE")
- plt.title("Ціна закриття акцій у часі")
- plt.xlabel("Дата")
- plt.ylabel("CLOSE")
- plt.grid(True)
- plt.legend()
- plt.tight_layout()
- plt.show()
- def r2_score(y_true: np.ndarray, y_pred: np.ndarray) -> float:
- y_true = np.asarray(y_true, dtype=float)
- y_pred = np.asarray(y_pred, dtype=float)
- ss_res = np.sum((y_true - y_pred) ** 2)
- ss_tot = np.sum((y_true - np.mean(y_true)) ** 2)
- return 1.0 - ss_res / ss_tot
- def fit_trend_models(x: np.ndarray, y: np.ndarray, series_name: str = ""):
- x = np.asarray(x, dtype=float)
- y = np.asarray(y, dtype=float)
- models = {}
- coeffs_lin = np.polyfit(x, y, deg=1)
- y_hat_lin = np.polyval(coeffs_lin, x)
- models["linear"] = {
- "y_hat": y_hat_lin,
- "r2": r2_score(y, y_hat_lin),
- "params": coeffs_lin,
- "formula": f"y = {coeffs_lin[1]:.4f} + {coeffs_lin[0]:.4f} * t",
- }
- if np.all(x > 0):
- lx = np.log(x)
- coeffs_log = np.polyfit(lx, y, deg=1)
- y_hat_log = np.polyval(coeffs_log, lx)
- models["logarithmic"] = {
- "y_hat": y_hat_log,
- "r2": r2_score(y, y_hat_log),
- "params": coeffs_log,
- "formula": f"y = {coeffs_log[1]:.4f} + {coeffs_log[0]:.4f} * ln(t)",
- }
- coeffs_poly2 = np.polyfit(x, y, deg=2)
- y_hat_poly2 = np.polyval(coeffs_poly2, x)
- models["poly2"] = {
- "y_hat": y_hat_poly2,
- "r2": r2_score(y, y_hat_poly2),
- "params": coeffs_poly2,
- "formula": (
- f"y = {coeffs_poly2[2]:.4f} + {coeffs_poly2[1]:.4f} * t + "
- f"{coeffs_poly2[0]:.4f} * t^2"
- ),
- }
- if np.all(y > 0):
- ly = np.log(y)
- coeffs_exp = np.polyfit(x, ly, deg=1)
- a = np.exp(coeffs_exp[1])
- b = coeffs_exp[0]
- y_hat_exp = a * np.exp(b * x)
- models["exponential"] = {
- "y_hat": y_hat_exp,
- "r2": r2_score(y, y_hat_exp),
- "params": (a, b),
- "formula": f"y = {a:.4f} * exp({b:.4f} * t)",
- }
- best_key = max(models.keys(), key=lambda k: models[k]["r2"])
- best_model = models[best_key]
- print(f"\n=== Підбір тренда для {series_name} ===")
- for name, m in models.items():
- print(f"{name:>12}: R^2 = {m['r2']:.4f}, формула: {m['formula']}")
- print(f"Найкраща модель для {series_name}: {best_key} з R^2 = {best_model['r2']:.4f}")
- return best_key, best_model, models
- def plot_trend(x: np.ndarray, y: np.ndarray, trend_model, series_name: str = "") -> None:
- x = np.asarray(x, dtype=float)
- y = np.asarray(y, dtype=float)
- y_hat = np.asarray(trend_model["y_hat"], dtype=float)
- plt.figure(figsize=(10, 5))
- plt.plot(x, y, label=f"{series_name} (вихідні дані)")
- plt.plot(x, y_hat, label=f"Тренд: {trend_model['formula']}", linewidth=2)
- plt.title(f"{series_name}: вихідні дані та лінія тренда")
- plt.xlabel("t")
- plt.ylabel(series_name)
- plt.grid(True)
- plt.legend()
- plt.tight_layout()
- plt.show()
- def linear_trend_two_ways(x: np.ndarray, y: np.ndarray):
- x = np.asarray(x, dtype=float)
- y = np.asarray(y, dtype=float)
- coeffs_polyfit = np.polyfit(x, y, deg=1)
- b1_polyfit, b0_polyfit = coeffs_polyfit[0], coeffs_polyfit[1]
- X_design = np.column_stack([np.ones_like(x), x])
- beta, *_ = np.linalg.lstsq(X_design, y, rcond=None)
- b0_lstsq, b1_lstsq = beta[0], beta[1]
- print("\n=== Лінійний тренд двома способами (аналог ЛИНЕЙН і 'Аналізу даних') ===")
- print(f"polyfit: y = {b0_polyfit:.4f} + {b1_polyfit:.4f} * t")
- print(f"lstsq (МНК): y = {b0_lstsq:.4f} + {b1_lstsq:.4f} * t")
- y_hat = b0_lstsq + b1_lstsq * x
- plt.figure(figsize=(10, 5))
- plt.plot(x, y, label="CLOSE (вихідні дані)")
- plt.plot(x, y_hat, label=f"Лінійний тренд (МНК): y = {b0_lstsq:.4f} + {b1_lstsq:.4f} * t", linewidth=2)
- plt.title("Ціна закриття та лінійний тренд")
- plt.xlabel("t (номер спостереження)")
- plt.ylabel("CLOSE")
- plt.grid(True)
- plt.legend()
- plt.tight_layout()
- plt.show()
- def moving_average_manual(values: np.ndarray, window: int) -> np.ndarray:
- values = np.asarray(values, dtype=float)
- n = len(values)
- result = np.full(n, np.nan)
- if window < 1 or window > n:
- return result
- half = window // 2
- for i in range(half, n - half):
- result[i] = np.mean(values[i - half : i + half + 1])
- return result
- def moving_average_convolve(values: np.ndarray, window: int) -> np.ndarray:
- values = np.asarray(values, dtype=float)
- if window < 1:
- return np.full_like(values, np.nan, dtype=float)
- kernel = np.ones(window) / window
- conv = np.convolve(values, kernel, mode="same")
- return conv
- def smooth_additive_series(
- df_dyn: pd.DataFrame,
- window_noise: int = WINDOW_NOISE,
- window_season: int = WINDOW_SEASON,
- ) -> pd.DataFrame:
- df = df_dyn.copy()
- t = df["t"].to_numpy()
- y = df["y_add"].to_numpy()
- ma_manual_short = moving_average_manual(y, window_noise)
- ma_rolling_short = pd.Series(y).rolling(window_noise, center=True).mean().to_numpy()
- ma_conv_short = moving_average_convolve(y, window_noise)
- ma_manual_long = moving_average_manual(y, window_season)
- ma_rolling_long = pd.Series(y).rolling(window_season, center=True).mean().to_numpy()
- ma_conv_long = moving_average_convolve(y, window_season)
- window_median = 5
- med_series = pd.Series(y).rolling(window_median, center=True).median().to_numpy()
- df["MA_manual_short"] = ma_manual_short
- df["MA_rolling_short"] = ma_rolling_short
- df["MA_conv_short"] = ma_conv_short
- df["MA_manual_long"] = ma_manual_long
- df["MA_rolling_long"] = ma_rolling_long
- df["MA_conv_long"] = ma_conv_long
- df["Median_5"] = med_series
- plt.figure(figsize=(10, 5))
- plt.plot(t, y, label="y_add (вихідний ряд)", alpha=0.5)
- plt.plot(t, ma_manual_short, label=f"MA manual (вікно={window_noise})")
- plt.plot(t, ma_rolling_short, label=f"MA rolling (вікно={window_noise})")
- plt.plot(t, ma_conv_short, label=f"MA convolve (вікно={window_noise})")
- plt.title("Згладжування y_add (видалення шуму, коротке вікно)")
- plt.xlabel("t")
- plt.ylabel("y_add")
- plt.grid(True)
- plt.legend()
- plt.tight_layout()
- plt.show()
- plt.figure(figsize=(10, 5))
- plt.plot(t, y, label="y_add (вихідний ряд)", alpha=0.5)
- plt.plot(t, ma_manual_long, label=f"MA manual (вікно={window_season})")
- plt.plot(t, ma_rolling_long, label=f"MA rolling (вікно={window_season})")
- plt.plot(t, ma_conv_long, label=f"MA convolve (вікно={window_season})")
- plt.title("Згладжування y_add (видалення шуму та сезонності, довге вікно)")
- plt.xlabel("t")
- plt.ylabel("y_add")
- plt.grid(True)
- plt.legend()
- plt.tight_layout()
- plt.show()
- plt.figure(figsize=(10, 5))
- plt.plot(t, y, label="y_add (вихідний ряд)", alpha=0.5)
- plt.plot(t, med_series, label=f"Ковзна медіана (вікно={window_median})", linewidth=2)
- plt.title("Ковзна медіана для y_add")
- plt.xlabel("t")
- plt.ylabel("y_add")
- plt.grid(True)
- plt.legend()
- plt.tight_layout()
- plt.show()
- return df
- def build_ohlc_resampled(df_hist: pd.DataFrame):
- ohlc_dict = {
- "OPEN": "first",
- "HIGH": "max",
- "LOW": "min",
- "CLOSE": "last",
- }
- ohlc_month = df_hist.resample("M").apply(ohlc_dict).dropna()
- ohlc_year = df_hist.resample("Y").apply(ohlc_dict).dropna()
- return ohlc_month, ohlc_year
- def plot_ohlc_charts(df_hist: pd.DataFrame) -> None:
- ohlc_month, ohlc_year = build_ohlc_resampled(df_hist)
- for df_ohlc, name in [(ohlc_month, "Місячні"), (ohlc_year, "Річні")]:
- data = df_ohlc.copy()
- data.index.name = "Date"
- data.rename(
- columns={
- "OPEN": "Open",
- "HIGH": "High",
- "LOW": "Low",
- "CLOSE": "Close",
- },
- inplace=True,
- )
- mpf.plot(
- data,
- type="candle",
- title=f"Свічковий графік ({name} дані)",
- style="yahoo",
- volume=False,
- )
- mpf.plot(
- data,
- type="ohlc",
- title=f"Графік барів ({name} дані)",
- style="yahoo",
- volume=False,
- )
- def main():
- print("=== Практична робота №7–8. Ряди динаміки. Варіант 2 ===")
- df_dyn = generate_dynamic_series()
- print("\nПерші 5 рядків згенерованих даних:")
- print(df_dyn.head())
- plot_dynamic_series(df_dyn)
- try:
- df_hist = load_historical_data()
- except FileNotFoundError:
- print(
- f"\nФайл {HIST_FILE} не знайдено. "
- f"Скопіюйте файл історичних даних у поточну папку і запустіть скрипт знову."
- )
- df_hist = None
- except Exception as e:
- print(f"\nПомилка при завантаженні історичних даних: {e}")
- df_hist = None
- if df_hist is not None:
- print("\nПерші 5 рядків історичних даних:")
- print(df_hist[["OPEN", "HIGH", "LOW", "CLOSE", "VOL"]].head())
- plot_close_prices(df_hist)
- t_dyn = df_dyn["t"].to_numpy()
- _, best_model_add, _ = fit_trend_models(t_dyn, df_dyn["y_add"], "y_add (адитивна)")
- plot_trend(t_dyn, df_dyn["y_add"], best_model_add, "y_add (адитивна)")
- _, best_model_mult, _ = fit_trend_models(
- t_dyn, df_dyn["y_mult"], "y_mult (мультиплікативна)"
- )
- plot_trend(t_dyn, df_dyn["y_mult"], best_model_mult, "y_mult (мультиплікативна)")
- if df_hist is not None:
- y_close = df_hist["CLOSE"].to_numpy()
- t_close = np.arange(1, len(y_close) + 1)
- _, best_model_close, _ = fit_trend_models(
- t_close, y_close, "CLOSE (історичні дані)"
- )
- plot_trend(t_close, y_close, best_model_close, "CLOSE (історичні дані)")
- linear_trend_two_ways(t_close, y_close)
- smooth_additive_series(df_dyn, window_noise=WINDOW_NOISE, window_season=WINDOW_SEASON)
- if df_hist is not None:
- plot_ohlc_charts(df_hist)
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment