Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

關於 Backtrader Multi Example #48

Open
kevin61303 opened this issue Aug 27, 2024 · 6 comments
Open

關於 Backtrader Multi Example #48

kevin61303 opened this issue Aug 27, 2024 · 6 comments

Comments

@kevin61303
Copy link

在看完第四章後 對於最後的 多商品交易的方法有興趣 但是看官方文件後 還是不太了解 不知道有沒有其他的網站 或是文章有更加詳細的解釋呢?

@arleigh418
Copy link
Owner

您好,我很高興收到您的問題。
沒問題的,我可以跟您分享做法,但您期待的多商品交易為何呢?

  1. 同類型且同樣計算方式的商品 (例如都是股票,要900隻)
  2. 不同類型且不同計算方式的產品 (例如同時交易台指期跟金融期,因為槓桿跟保證金不一樣,所以在技術上算是不同的產品,要分開設置)

@kevin61303
Copy link
Author

作者您好,感謝你的回復:
根據書上看到的內容我應該更偏向於 第一種 同類型且同樣計算方式的商品 ,用一筆初始資金 ,同樣的策略 在不同的股票進行投資。

@arleigh418
Copy link
Owner

您好,萬分抱歉,近期忙碌沒有注意到後來您有回覆。
如果之後我在 48 小時內沒有回覆的話,請您再留言一次或是寄信給我:arleigh668@gmail.com
真的非常抱歉,我稍後整理一下今天之內會提供您範例。

@arleigh418
Copy link
Owner

您好,我提供一個簡單的我自己在做的範例供您參考。
如果是多個股票, backtrader是利用 cerebro.adddata(data, name=stock_id) 裡面的 name 來控制的,所以可以賦予每一個喂進去的股票資料一個 name,例如我們這裡使用每一個股票代號當作每一個股票數據的 name。

if __name__ == '__main__':
    cerebro = bt.Cerebro()
    cerebro.addstrategy(SimpleMAStrategy)
    stock_list = ['2330', '2317', '0050']
    for stock_id in stock_list:
        file_path = f"backtest_data/{stock_id}.xlsx"
        if os.path.exists(file_path):
            df = pd.read_excel(file_path, parse_dates=['date'])
            df["date"] = pd.to_datetime(df["date"])
            df.set_index('date', inplace=True)
            data = bt.feeds.PandasData(dataname=df)
            cerebro.adddata(data, name=stock_id)
        else:
            print(f"File not found: {file_path}")

    cerebro.broker.setcash(1000000.0)
    cerebro.broker.setcommission(commission=0.001)

    print("Starting Portfolio Value: %.2f" % cerebro.broker.getvalue())
    cerebro.run()
    print("Final Portfolio Value: %.2f" % cerebro.broker.getvalue())

@arleigh418
Copy link
Owner

當您在撰寫策略時,在製作指標就可以用一個 dict 來儲存,因為 add_data 多筆的關係,此時 self.datas 裡面就會有多筆資料,所以我們需要 loop 他,而我們可以透過 data._name 來取得我們剛剛為每一筆資料賦予的名字,這時我們就可以處理多個不同的股票了。

class SimpleMAStrategy(bt.Strategy):
    params = (
        ('short_period', 20),
        ('long_period', 50),
    )

    def __init__(self):
        self.ma_short = {}
        self.ma_long = {}

        for data in self.datas:
            self.ma_short[data._name] = bt.indicators.SimpleMovingAverage(
                data.close, period=self.params.short_period
            )
            self.ma_long[data._name] = bt.indicators.SimpleMovingAverage(
                data.close, period=self.params.long_period
            )

    def log(self, txt, dt=None):
        dt = dt or self.datas[0].datetime.date(0)
        print(f"{dt.isoformat()} {txt}")

    def next(self):
        for data in self.datas:
            if self.ma_short[data._name] > self.ma_long[data._name]:
                if not self.getposition(data):
                    self.buy(data=data)
                    self.log(f"BUY ORDER - Stock: {data._name}, Price: {data.close[0]}")
            elif self.ma_short[data._name] < self.ma_long[data._name]:
                if self.getposition(data):
                    self.sell(data=data)
                    self.log(f"SELL ORDER - Stock: {data._name}, Price: {data.close[0]}")

@kevin61303
Copy link
Author

非常感謝,親切的作者 ,您提供的範例我會好好研究,再次感謝您抽出時間來為我們解惑。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants