Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

臺股個股線圖繪製

https://hackmd.io/@s02260441/Hki9NN5jL

import pandas as pd
import datetime as datetime
import matplotlib
import mplfinance as mpf
import pandas_datareader as pdr

# 導入pandas、matplotlib、mplfinance模組,將mplfinance模組縮寫為mpf
# 這邊要導入matplotlib的原因是因為mplfinance繪圖時需要調用mptplotlib模組

target_stock = "2330.TW"  # 設定要繪製走勢圖的股票
start = datetime.datetime(2018, 4, 1)
df = pdr.DataReader("2330.TW", "yahoo", start=start)
print(df)


mc = mpf.make_marketcolors(up="r", down="g", inherit=True)
s = mpf.make_mpf_style(base_mpf_style="yahoo", marketcolors=mc)
# 針對線圖的外觀微調,將上漲設定為紅色,下跌設定為綠色,符合臺股表示習慣
# 接著把自訂的marketcolors放到自訂的style中,而這個改動是基於預設的yahoo外觀

kwargs = dict(
    type="candle",
    mav=(5, 20, 60),
    volume=True,
    figratio=(10, 8),
    figscale=0.75,
    title=target_stock,
    style=s,
)
# 設定可變參數kwargs,並在變數中填上繪圖時會用到的設定值

mpf.plot(df, **kwargs)
# 選擇df資料表為資料來源,帶入kwargs參數,畫出目標股票的走勢圖

https://yhhuang1966.blogspot.com/2022/09/python-mplfinance.html

# https://python.plainenglish.io/plot-stock-chart-using-mplfinance-in-python-9286fc69689
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
import mplfinance as mpf

# download stock price data
symbol = "AAPL"
df = yf.download(symbol, period="6mo")

# Add MACD as subplot
def MACD(df, window_slow, window_fast, window_signal):
    macd = pd.DataFrame()
    macd["ema_slow"] = df["Close"].ewm(span=window_slow).mean()
    macd["ema_fast"] = df["Close"].ewm(span=window_fast).mean()
    macd["macd"] = macd["ema_slow"] - macd["ema_fast"]
    macd["signal"] = macd["macd"].ewm(span=window_signal).mean()
    macd["diff"] = macd["macd"] - macd["signal"]
    macd["bar_positive"] = macd["diff"].map(lambda x: x if x > 0 else 0)
    macd["bar_negative"] = macd["diff"].map(lambda x: x if x < 0 else 0)
    return macd


macd = MACD(df, 12, 26, 9)
macd_plot = [
    mpf.make_addplot(
        (macd["macd"]), color="#606060", panel=2, ylabel="MACD", secondary_y=False
    ),
    mpf.make_addplot((macd["signal"]), color="#1f77b4", panel=2, secondary_y=False),
    mpf.make_addplot((macd["bar_positive"]), type="bar", color="#4dc790", panel=2),
    mpf.make_addplot((macd["bar_negative"]), type="bar", color="#fd6b6c", panel=2),
]

mpf.plot(df, type="candle", volume=True, addplot=macd_plot)
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
import mplfinance as mpf
import talib as ta

# download stock price data
symbol = "AAPL"
df = yf.download(symbol, start="2021-01-01", end="2022-05-01")
for num in [10, 120]:
    df[f"SMA{num}"] = ta.SMA(df["Close"], timeperiod=num)

df["CLOSE_LINEARREG_ANGLE"] = ta.LINEARREG_ANGLE(df["Close"], timeperiod=14)
df["SMA_LINEARREG_ANGLE"] = ta.LINEARREG_ANGLE(df["SMA10"], timeperiod=14)
df = df.dropna()

add_plot = [
    mpf.make_addplot(df["CLOSE_LINEARREG_ANGLE"]),
    mpf.make_addplot(df["SMA_LINEARREG_ANGLE"]),
]
mc = mpf.make_marketcolors(up="r", down="g", inherit=True)
mpf.plot(
    df,
    type="candle",
    volume=True,
    style=mpf.make_mpf_style(base_mpf_style="yahoo", marketcolors=mc),
    addplot=add_plot,
)
from binance.client import Client
import pandas as pd
import matplotlib.pyplot as plt
import mplfinance as mpf
import talib as ta
import datetime as dt
import json
import os


class binanceAPI:
    def __init__(self, configPath):
        with open(configPath, "r") as f:
            self.kw_login = json.loads(f.read())
        self.api = self.__login(self.kw_login["PUBLIC"], self.kw_login["SECRET"])

    def __login(self, PUBLIC, SECRET):
        return Client(api_key=PUBLIC, api_secret=SECRET)


def build_df(klines):
    cols = [
        "timestamp",
        "open",
        "high",
        "low",
        "close",
        "volume",
        "close_time",
        "quote_av",
        "trades",
        "tb_base_av",
        "tb_quote_av",
        "ignore",
    ]
    df = pd.DataFrame(klines, columns=cols)
    df["timestamp"] = [dt.datetime.fromtimestamp(x / 1000.0) for x in df["timestamp"]]
    df.set_index("timestamp", inplace=True)
    df = df[["open", "high", "low", "close", "volume"]]
    df[["open", "high", "low", "close", "volume"]] = df[
        ["open", "high", "low", "close", "volume"]
    ].astype(float)
    for num in [5, 10, 120]:
        df[f"SMA{num}"] = ta.SMA(df["close"], timeperiod=num)
    df["SMA_LINEARREG_ANGLE"] = ta.LINEARREG_ANGLE(df["SMA5"], timeperiod=14)
    df["CLOSE_LINEARREG_ANGLE"] = ta.LINEARREG_ANGLE(df["close"], timeperiod=14)
    df = df.dropna()
    df["idx"] = range(0, len(df))
    return df


if __name__ == "__main__":
    client = binanceAPI(os.environ["HOME"] + f"/.mybin/jason/binance_login.txt")
    KLINE_INTERVAL = Client.KLINE_INTERVAL_30MINUTE
    start_time = dt.datetime(2022, 11, 1, hour=8, minute=00, second=0)
    end_time = dt.datetime.now()

    klines = client.api.get_historical_klines(
        symbol="BTCUSDT",
        interval=KLINE_INTERVAL,
        start_str=start_time.strftime("%Y-%m-%d %H:%M:%S"),
        end_str=end_time.strftime("%Y-%m-%d %H:%M:%S"),
    )
    df = build_df(klines)
    print(df.to_markdown())
    input()
    add_plot = [
        mpf.make_addplot(df["CLOSE_LINEARREG_ANGLE"]),
        mpf.make_addplot(df["SMA_LINEARREG_ANGLE"]),
    ]
    mc = mpf.make_marketcolors(up="r", down="g", inherit=True)
    mpf.plot(
        df,
        type="candle",
        volume=True,
        style=mpf.make_mpf_style(base_mpf_style="yahoo", marketcolors=mc),
        addplot=add_plot,
    )

# Function.py
# 載入套件
import yfinance as yf
import mplfinance as mpf
import numpy as np

# 透過Yfinance取得K棒歷史資料
def GetKBar(SDate, EDate, Prod, Kind, Cycle):
    # 轉換日期格式
    SDate = SDate[:4] + "-" + SDate[4:6] + "-" + SDate[6:]
    EDate = EDate[:4] + "-" + EDate[4:6] + "-" + EDate[6:]
    # 指數前面要加 ^ 符號
    if Kind == "Index":
        Prod = "^" + Prod
    # 從 yahoo finance 下載資料
    Data = yf.download(Prod, start=SDate, end=EDate, interval=Cycle)
    # 將欄位名稱改為英文小寫
    Data.columns = [i.lower() for i in Data.columns]
    # 因python會有小數點精確度問題,故將股價取到小數後兩位
    Data.open = [round(i, 2) for i in Data.open]
    Data.high = [round(i, 2) for i in Data.high]
    Data.low = [round(i, 2) for i in Data.low]
    Data.close = [round(i, 2) for i in Data.close]
    return Data


# 圖片物件
class DrawKBar:
    # 初始設定
    def __init__(self, KBar):
        self.KBar = KBar
        self.TableList = []

    # 新增附圖
    def Add(
        self,
        data,
        panel=0,
        type="line",
        marker=".",
        color="black",
        scatter=False,
        ylabel="",
    ):
        # Table = mpf.make_addplot(data,panel=panel,type=type,color=color)
        Table = mpf.make_addplot(
            data,
            panel=panel,
            type=type,
            marker=marker,
            color=color,
            scatter=scatter,
            ylabel=ylabel,
            secondary_y=False,
        )
        self.TableList.append(Table)

    # 顯示圖片
    def Show(self):
        KBar_color = mpf.make_marketcolors(
            up="red", down="green", edge="inherit", wick="inherit", volume="inherit"
        )
        KBar_style = mpf.make_mpf_style(
            base_mpf_style="yahoo", edgecolor="black", marketcolors=KBar_color
        )
        mpf.plot(
            self.KBar,
            type="candle",
            style=KBar_style,
            volume=True,
            addplot=self.TableList,
        )


# 計算績效KPI
def GetKPI(ProfitList):
    # 將 List 轉為 numpy array 格式
    ProfitList = np.array(ProfitList)
    print()

    # 交易次數
    TotalNum = len(ProfitList)
    print("交易次數:", TotalNum, "次")

    # 總損益
    TotalProfit = round(sum(ProfitList), 2)
    print("總損益:", TotalProfit, "元")

    # 平均損益
    if TotalNum == 0:
        AvgProfit = None
    else:
        AvgProfit = round(TotalProfit / TotalNum, 2)
    print("平均損益:", AvgProfit, "元")

    # 總勝率
    Win = [i for i in ProfitList if i > 0]  # 獲利的部分
    Loss = [i for i in ProfitList if i < 0]  # 虧損的部分
    if TotalNum == 0:
        WinRate = None
    else:
        WinRate = round(len(Win) / TotalNum * 100, 2)
    print("總勝率:", WinRate, "%")

    # 平均獲利
    if len(Win) == 0:
        AvgWin = None
    else:
        AvgWin = round(np.mean(Win), 2)
    print("平均獲利:", AvgWin, "元")

    # 平均虧損
    if len(Loss) == 0:
        AvgLoss = None
    else:
        AvgLoss = round(np.mean(Loss), 2)
    print("平均虧損:", AvgLoss, "元")

    # 獲利因子
    if sum(Loss) == 0:
        ProfitFactor = None
    else:
        ProfitFactor = round(sum(Win) / abs(sum(Loss)), 2)
    print("獲利因子:", ProfitFactor, "倍")

    # 最大資金回落
    MaxCapital = 0
    Capital = 0
    MDD = 0
    DD = 0
    for i in ProfitList:
        Capital += i
        MaxCapital = max(MaxCapital, Capital)
        DD = round(MaxCapital - Capital, 2)
        MDD = max(MDD, DD)
    print("最大資金回落:", abs(MDD), "元")
# python 8-2.py "20210101" "20220501"  "AAPL" ""  "1D"
# 載入套件
from plotly.offline import plot
import talib as ta
import plotly.graph_objs as go
import sys, Function

# 資料參數 (可自行調整)
SDate = sys.argv[1]  # 資料起始日
EDate = sys.argv[2]  # 資料結束日
Prod = sys.argv[3]  # 商品代碼
Kind = sys.argv[4]  # 商品種類
Cycle = sys.argv[5]  # K棒週期

# 取得K棒資料
KBar = Function.GetKBar(SDate, EDate, Prod, Kind, Cycle)
print(KBar)

# 計算技術指標
flag = False
KBar["CDL3BLACKCROWS"] = ta.CDL3BLACKCROWS(
    KBar["open"], KBar["high"], KBar["low"], KBar["close"]
)
print(KBar)
print(KBar["CDL3BLACKCROWS"].tolist(), len(KBar["CDL3BLACKCROWS"]))
for i in range(0, len(KBar["CDL3BLACKCROWS"])):
    signal = KBar.iloc[0]["CDL3BLACKCROWS"]
    if float(signal) < 0:
        print(KBar.index[i], signal)
        flag = True

if flag == False:
    print("期間內無觸發此型態訊號")

trace = go.Candlestick(  # x= pd.to_datetime(dfohlc.index.values),
    open=KBar["open"], high=KBar["high"], low=KBar["low"], close=KBar["close"]
)
data = [trace]

plot(data, filename="go_candle1.html")