[PYTHON] Create basic algorithms with Smart Trade

What is Smart Trade

What is Smart Trade? The name of the stock investment algorithm development platform service provided by Smart Trade Ltd. ~~ Currently the beta version, but the official version will be released soon ~~ (Added on 2017/11/25: Official version released on 2017/11/20, service name is also "QuantX")

It has a function that allows you to write trading algorithms using Python and easily perform backtesting.

The following can use the service from HP https://smarttrade.co.jp

Referenced link

Create an algorithm by referring to the Qiita post below HP also has a sample algorithm, so you can refer to it as well. We are waiting for the enhancement of the tutorial

Try to develop an investment algorithm with Python 1 http://qiita.com/hiroshimoda/items/e89444729fe7d25c0275

Building Algorithmic Strategies on SmartTrade http://qiita.com/vinyip918/items/8623c5e902b113becd38

How to write an algorithm

tutorial

Below is a simple tutorial https://beta.smarttrade.co.jp/handbook/ja/

Algorithm configuration

Algorithms on Smart Trade are roughly divided into three. Each has the following functions

Initialization

In initialization, the market to be used in the algorithm (Japanese stocks, Chinese stocks), the stock to be traded, and the price to be used (closing price, high price, etc.) are set.

initialize.py


def initialize(ctx):
 ctx.configure(
  target="jp.stock.daily",
  channels={#Channel used
            "jp.stock": {"symbols": ["jp.stock.7203"],
                         "columns": [ "high_price_adj",       
                                      "low_price_adj","close_price",
                                      "close_price_adj","volume_adj",]
                        }})

Signal definition

Describe the algorithm that outputs a buy / sell signal in the signal definition section. This time, using MACD, the histogram of MACD is ・ Convert from minus to plus: buy ・ Conversion from plus to minus: Sell Create a simple algorithm called

algorism.py


def _TALIB_CALL(data):
    #Define the value to use
      hp = data["high_price_adj"].fillna(method="ffill")
      lp = data["low_price_adj"].fillna(method="ffill")
      cp = data["close_price_adj"].fillna(method="ffill")

    #Define variables
      result_macd = {}
      result_macdsignal = {}
      result_macdhist = {}
      result = pd.DataFrame(data=0,columns=cp.columns, index=cp.index)

      for (sym,val) in cp.items():#MACD for each brand,MACD signal,Calculate MACD histogram
        
        result_macd[sym], result_macdsignal[sym], result_macdhist[sym] = ta.MACD(cp[sym].values.astype(np.double),
                                     fastperiod=12, slowperiod=26, signalperiod=9)

        macd = pd.DataFrame(data=result_macd,columns=cp.columns, index=cp.index)
        macdsignal = pd.DataFrame(data=result_macdsignal,columns=cp.columns, index=cp.index)
        macdhist = pd.DataFrame(data=result_macdhist,columns=cp.columns, index=cp.index)

        #Crossing judgment
        test = np.sign( macdhist[sym].values[1:]) - np.sign(macdhist[sym].values[:-1])
        n = len(test)
        for i, row in enumerate(test):
          result[sym][i+1] = 0 if isNaN(test[i]) else test[i]
      
      
      #Define trading signals
      buy_sig = result[result >= 2]
      sell_sig = result[result <= -2]
      
      return {
            "macd": macd,
            "macdsignal": macdsignal,
            "macdhist": macdhist,
            "buy:sig": buy_sig,
            "sell:sig": sell_sig,
      }
    #Signal registration
    ctx.regist_signal("TALIB_CALL", _TALIB_CALL)

Trading execution

In the trading execution section, describe the quantity to be bought and sold, profitability, and loss cut criteria based on the algorithm described in the signal definition.

handle_signals.py


def handle_signals(ctx, date, current):
    
    #Processing when a buy signal is issued
    buy = current["buy:sig"].dropna()
    for (sym, val) in buy.items():

        sec = ctx.getSecurity(sym)
        sec.order(sec.unit()*1, comment="Buy signal(%f)" % val)
        pass
      
   #Processing when a sell signal is issued
    sell = current["sell:sig"].dropna()
    for (sym, val) in sell.items():

        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0, comment="Signal sale(%f)" % val)
        pass

    pass

Whole algorithm

MACD.py



import pandas as pd
import talib as ta
import numpy as np
def isNaN(num):
    return num != num


def initialize(ctx):
    #pp.pprint(vars(ctx))
    # print(ctx.positions)

    #Setting
    ctx.configure(
        target="jp.stock.daily",
        channels={          #Channel used
            "jp.stock": {
              "symbols": [
                "jp.stock.7203",  "jp.stock.7267",
                "jp.stock.7270",  "jp.stock.7269",
                "jp.stock.7259",  "jp.stock.7202",
                "jp.stock.7203",  "jp.stock.7205",
                "jp.stock.7208",  "jp.stock.7211",
                "jp.stock.7211",  "jp.stock.7276",
                "jp.stock.7272",  "jp.stock.7240",
                "jp.stock.3116",  "jp.stock.7282",
                "jp.stock.7248",  "jp.stock.7313",
                "jp.stock.6995",  "jp.stock.7222",
                "jp.stock.7278",  "jp.stock.7242",
                "jp.stock.7287",  "jp.stock.7251",
                "jp.stock.7230",  "jp.stock.5949",
                "jp.stock.7296",  "jp.stock.7279",
                "jp.stock.7250",  "jp.stock.5970",
                "jp.stock.7220",
              ],
              "columns": [ "high_price_adj", "low_price_adj","close_price",        #closing price
            "close_price_adj",    #closing price(After stock split adjustment) 
            "volume_adj",         #Volume
      ]
      }
      }
    )
    
    # talib sample...
    def _TALIB_CALL(data):

      hp = data["high_price_adj"].fillna(method="ffill")
      lp = data["low_price_adj"].fillna(method="ffill")
      cp = data["close_price_adj"].fillna(method="ffill")


      result_macd = {}
      result_macdsignal = {}
      result_macdhist = {}
      result = pd.DataFrame(data=0,columns=cp.columns, index=cp.index)

      for (sym,val) in cp.items():
        
        result_macd[sym], result_macdsignal[sym], result_macdhist[sym] = ta.MACD(cp[sym].values.astype(np.double),
                                     fastperiod=12, slowperiod=26, signalperiod=9)

        macd = pd.DataFrame(data=result_macd,columns=cp.columns, index=cp.index)
        macdsignal = pd.DataFrame(data=result_macdsignal,columns=cp.columns, index=cp.index)
        macdhist = pd.DataFrame(data=result_macdhist,columns=cp.columns, index=cp.index)

      
        test = np.sign( macdhist[sym].values[1:]) - np.sign(macdhist[sym].values[:-1])
        n = len(test)
        for i, row in enumerate(test):
          result[sym][i+1] = 0 if isNaN(test[i]) else test[i]
      
      
      
      buy_sig = result[result >= 2]
      sell_sig = result[result <= -2]
      
      return {
            "macd": macd,
            "macdsignal": macdsignal,
            "macdhist": macdhist,
            "buy:sig": buy_sig,
            "sell:sig": sell_sig,
      }

    
    #Signal registration
    ctx.regist_signal("TALIB_CALL", _TALIB_CALL)

def handle_signals(ctx, date, current):
    
    buy = current["buy:sig"].dropna()
    for (sym, val) in buy.items():

        sec = ctx.getSecurity(sym)
        sec.order(sec.unit()*1, comment="Buy signal(%f)" % val)
        pass
      
    sell = current["sell:sig"].dropna()
    for (sym, val) in sell.items():

        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0, comment="Signal sale(%f)" % val)
        pass

    pass

result

The following output appears for the overall profit and loss スクリーンショット 2017-08-27 14.13.25.png

It is possible to visually check the trading results for individual stocks. The red circle is the buy signal and the blue circle is the sell signal. スクリーンショット 2017-08-27 14.15.05.png

When the MACD histogram alone is output, the output will be as follows. スクリーンショット 2017-08-27 14.15.26.png

By superimposing it on the stock price chart, you can confirm that you can buy and sell properly at the point where the MACD histogram intersects 0. However, there are some parts that are not bought or sold even if they cross 0, and it can be presumed that they could not be bought or sold due to the balance with the overall position at that time, but confirmation is necessary スクリーンショット 2017-08-27 14.15.47.png

How it will be done in the future

I want to learn time-series data analysis methods and create algorithms that can capture so-called "double bottom" and "bearish and bullish dissociation".

Recommended Posts

Create basic algorithms with Smart Trade
Create games with Pygame
Create filter with scipy
Create an environment with virtualenv
Create Cloud TPU with tf-nightly
Create an API with Django
BASIC authentication with Python bottle
Create / search / create table with PynamoDB
Create 3d gif with python3
Create graph with plotly button
[Python] Using OpenCV with Python (Basic)
Create a homepage with django
Create Image Viewer with Tkinter
Create custom rules with ElastAlert
Create patent map with Streamlit
Create a heatmap with pyqtgraph
[Python] [SQLite3] Operate SQLite with Python (Basic)
Create a directory with python
Create xlsx file with XlsxWriter
I wanted to create a smart presentation with Jupyter Notebook + nbpresent