株のシステムトレードをしよう - 1から始める株自動取引システムの作り方

株式をコンピュータに売買させる仕組みを少しずつ作っていきます。できあがってから公開ではなく、書いたら途中でも記事として即掲載して、後から固定ページにして体裁を整える方式で進めていきます。

バックテスト中に手仕舞いする ◆ Backtrader 最初の戦略その4.0

前回の振り返り

前回は、株式を買うことで建玉を作った。

how-to-make-stock-trading-system.dogwood008.com

今回の内容

建玉を手仕舞い(売る)ことで、含み益または含み損を確定させる。また、どのようなタイミングで売買しているかをグラフにプロットする。

解説が間に合っていないのと、まだソースコードは調整中だが、「時間を掛けて良いものより、短期間にそこそこのものを出して、後から磨く」というこのブログのポリシーを守るため、まだ改訂するが一旦掲載する。

次回も続きをするが、おそらく今回と同じように全部整う前にちょい出しすることになると思われる。

main.py

# from __future__ import (absolute_import, division, print_function,
#                        unicode_literals)

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])

# Import the backtrader platform
import backtrader as bt
from backtrader import Order

# ログ用
from logging import getLogger, StreamHandler, Formatter, DEBUG, INFO, WARN

# Create a Stratey
class TestStrategyWithLogger(bt.Strategy):
    params = (
        ('size', 1000),
    )
    def _log(self, txt, loglevel=INFO, dt=None):
        ''' Logging function for this strategy '''
        dt = dt or self.datas[0].datetime.date(0)
        self._logger.log(loglevel, '%s, %s' % (dt.isoformat(), txt))

    def _debug(self, txt, dt=None):
        self._log(txt, DEBUG, dt)

    def _info(self, txt, dt=None):
        self._log(txt, INFO, dt)

    def __init__(self, loglevel=DEBUG):
        # Keep a reference to the "close" line in the data[0] dataseries
        self._dataclose = self.datas[0].close
        self._logger = getLogger(__name__)
        self.handler = StreamHandler()
        self.handler.setLevel(loglevel)
        self._logger.setLevel(DEBUG)
        self._logger.addHandler(self.handler)
        self._logger.propagate = False
        self.handler.setFormatter(
                Formatter('[%(levelname)s] %(message)s'))


    def notify_order(self, order: Order) -> None:
        ''' backtraderから呼ばれる '''
        if order.status == Order.Completed:
            if order.isbuy():
                self._info('BUY: %.2f' % order.executed.price)

    def next(self):
        # Simply log the closing price of the series from the reference
        self._debug('[Close, position] = %.2f, %s' % (self._dataclose[0], self.getposition()))

        if self._dataclose[0] < self._dataclose[-1]:
            # current close less than previous close

            if self._dataclose[-1] < self._dataclose[-2]:
                # previous close less than the previous close

                # BUY, BUY, BUY!!! (with all possible default parameters)
                self._info('BUY CREATE, %.2f' % self._dataclose[0])
                self.buy(size=self.params.size)

            if self._dataclose[-2] * .97 > self._dataclose[-1]:
                # 前日が前々日の3%を超える下落時に手仕舞い
                self.close()

if __name__ == '__main__':
    # Create a cerebro entity
    cerebro = bt.Cerebro()

    # Add a strategy
    IN_DEVELOPMENT = True
    loglevel = DEBUG if IN_DEVELOPMENT else WARN
    cerebro.addstrategy(TestStrategyWithLogger, loglevel)

    # Datas are in a subfolder of the samples. Need to find where the script is
    # because it could have been called from anywhere
    modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
    datapath = os.path.join(modpath, '/opt/backtrader/datas/orcl-1995-2014.txt')

    # Create a Data Feed
    data = bt.feeds.YahooFinanceCSVData(
        dataname=datapath,
        # Do not pass values before this date
        fromdate=datetime.datetime(2000, 1, 1),
        # Do not pass values after this date
        todate=datetime.datetime(2000, 12, 31),
        reverse=False)

    # Add the Data Feed to Cerebro
    cerebro.adddata(data)

    # Set our desired cash start
    cerebro.broker.setcash(100000.0)

    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Run over everything
    cerebro.run()

    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

    width_inch = 16
    height_inch = 9
    figure = cerebro.plot(style='candlebars', width=width_inch, height=height_inch)[0][0]
    figure.savefig('plot.png')
# Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
backtrader = "*"
matplotlib = "==3.2.2"

[requires]
python_version = "3.8"

(C) 2020 dogwood008 禁無断転載 不許複製 Reprinting, reproducing are prohibited.