[PYTHON] J'ai essayé d'implémenter une ligne moyenne mobile de volume avec Quantx

Auto-introduction

Je m'appelle Masukawa (https://www.facebook.com/ryozodesert) et je suis stagiaire chez Smart Trade Co., Ltd., étudiant de deuxième année à la Faculté des sciences et de la technologie d'une certaine université M. .. Je suis encore un débutant, donc je suis sûr qu'il y a beaucoup de choses dont je ne suis pas sûr, mais j'espère que vous resterez avec moi jusqu'à la fin.

Que faire dans cet article

Puisqu'il s'agit de la troisième semaine de notre stage, j'aimerais vous présenter l'algorithme implémenté dans Quantx Factory. Cette fois, nous allons implémenter un algorithme de trading d'actions utilisant le ** volume moyen mobile **, qui est l'un des fameux indicateurs techniques.

Qu'est-ce que QuantX Factory?

Smart Trade Co., Ltd.

Démocratie financière

Sur la base de cette philosophie, nous avons développé "QuantX Factory", une plate-forme sur laquelle tout le monde peut facilement développer des algorithmes de trading.

Forces

Sujet principal

Comprendre le fonctionnement de la ligne de moyenne mobile du volume

Qu'est-ce que le volume

――Le nombre d'actions vendues ce jour-là ――Vous pouvez saisir l'activité d'achat et de vente -L'histogramme en bas de l'image ci-dessous

alt

** "Le volume précède le cours de l'action" **

On dit qu'il y a un changement dans le volume des transactions avant le mouvement des cours des actions. En d'autres termes, si vous utilisez la moyenne mobile du volume </ font>, vous pouvez trouver des signes d'achat et de vente plus rapidement.

Qu'est-ce qu'une ligne moyenne mobile?

alt

  • Un graphique en traits pointillés qui trace la valeur moyenne obtenue en additionnant les cours de clôture pendant plusieurs jours et en divisant par le nombre de jours. ―― En observant les deux lignes, «ligne à court terme» et «ligne à long terme», identifiez les signes d'achat et de vente
  • Ligne à court terme: ligne moyenne mobile avec jours de référence courts (généralement 5 jours) --Ligne à long terme: ligne moyenne mobile avec de longs jours de référence (généralement 25 jours) -Acheter chez Golden Cross </ font> et donner un signal de vente à Dead Cross </ font>
  • Pour plus de détails, veuillez consulter ici.

Que sont Golden Cross et Dead Cross?

  • ** Golden Cross: moneybag: ** </ font> alt ――C'est le moment où la ligne à court terme dépasse la ligne à long terme, indiquant que la tendance baissière se transforme en tendance haussière.

  • ** Utilisé comme signe d'achat **

  • ** Dead Cross ** </ font>: crâne: alt ―― Le moment où la ligne à court terme tombe en dessous de la ligne à long terme, cela indique que la tendance haussière se transforme en tendance baissière.

  • ** Utilisé comme signe de vente **

Quelle est la ligne moyenne mobile du volume?

  • Au lieu du cours de clôture pendant plusieurs jours, la moyenne mobile du volume </ font> pendant plusieurs jours est prise.
  • La façon d'émettre des signaux d'achat et de vente est la même que celle de la moyenne mobile.
Statut de ligne à court terme et à long terme Ligne directrice pour le jugement
La croix d'or se produit Acheter signal
Ligne à court terme>Ligne à long terme Tendance haussière
Ligne à court terme<Ligne à long terme Tendance à la baisse
La croix morte se produit Signe de vente

code


# Sample Algorithm
#Importation de bibliothèque
#Bibliothèque requise
import maron
import maron.signalfunc as sf
import maron.execfunc as ef
#Bibliothèque supplémentaire
#Veuillez consulter les notes sur l'écran de droite pour les bibliothèques qui peuvent être utilisées ①
import pandas as pd
import talib as ta
import numpy as np

#Méthode de commande(Veuillez décommenter un seul des deux suivants selon la méthode de commande souhaitée)
#Veuillez consulter la note sur l'écran de droite pour la méthode de commande ②
#ot = maron.OrderType.MARKET_CLOSE #Ordre au moment du cours de clôture le lendemain de l'émission du signal
ot = maron.OrderType.MARKET_OPEN   #Commande au moment du cours d'ouverture le lendemain de l'émission du signal
#ot = maron.OrderType.LIMIT        #Limiter l'ordre

#Acquisition de stocks et de colonnes
#Veuillez consulter la note sur l'écran de droite pour la désignation de la marque ③
#Veuillez consulter la note sur l'écran de droite pour obtenir les colonnes ④
def initialize(ctx):
  #Réglage
  ctx.logger.debug("initialize() called")
  ctx.high_term = 10
  ctx.holding_days = 5
  ctx.configure(
    channels={               #Canal utilisé
      "jp.stock": {
        "symbols": [
            "jp.stock.2914", #JT(L'industrie japonaise du tabac)
            "jp.stock.8766", #Tokio Marine Holdings
            "jp.stock.8031", #Mitsui Bussan
            "jp.stock.8316", #Groupe financier Sumitomo Mitsui
            "jp.stock.8411", #Groupe financier Mizuho
            "jp.stock.9437", #NTT Docomo
            "jp.stock.4502", #Industrie pharmaceutique Takeda
            "jp.stock.8058", #Mitsubishi Corporation
            "jp.stock.9433", #KDDI
            "jp.stock.9432", #Téléphone Nippon Telecom
            "jp.stock.7267", #Honda (Honda Giken Kogyo)
            "jp.stock.8306", #Groupe financier Mitsubishi UFJ
            "jp.stock.4503", #Astellas Pharmaceutical
            "jp.stock.4063", #Industrie chimique Shinetsu
            "jp.stock.7974", #Nintendo
            "jp.stock.6981", #Murata Seisakusho
            "jp.stock.3382", #Seven & i Holdings
            "jp.stock.9020", #Chemin de fer de passagers de l'est du Japon
            "jp.stock.8802", #Domaine Mitsubishi
            "jp.stock.9022", #Chemin de fer de passagers de Tokai
            "jp.stock.9984", #Groupe Softbank
            "jp.stock.6861", #Keyence
            "jp.stock.6501", #Hitachi, Ltd.
            "jp.stock.6752", #Panasonic
            "jp.stock.6758", #Sony
            "jp.stock.6954", #Fanac
            "jp.stock.7203", #Moteur Toyota
            "jp.stock.7751", #Canon
            "jp.stock.4452", #Kao
            "jp.stock.6098", #Recruter Holdings
        ],
        "columns": [
          "close_price",     #le dernier prix
          "close_price_adj", #le dernier prix(Après ajustement pour le fractionnement d'actions)
          "volume_adj",     #Le volume
          #"txn_volume",     #Prix de négociation
        ]
      }
    }
  )
  
  #Définition du signal
  def _my_signal(data):
    #Obtenez des données de volume
    vol = data["volume_adj"].fillna(method = "ffill")
    

    syms = data.minor_axis   #Créer une liste de stock
    dates = data.major_axis  #Créer une liste de dates
   
  
    #Moyenne mobile du volume
    mav5 = vol.rolling(window = 5, center = False).mean()
    mav25 = vol.rolling(window = 25, center = False).mean()
    
    ratio = mav5 / mav25
       
    #Croix d'or, croix morte de ligne moyenne mobile de volume
    vol_golden = (ratio >= 1.04) & (ratio.shift(1) < 1.0) #(mav5 > mav25) & (mav5.shift(1) < mav25.shift(1))
    vol_dead = (ratio <= 0.97)  & (ratio.shift(1) > 1.0)  #(mav5 < mav25) & (mav5.shift(1) > mav25.shift(1))
    #La méthode de décalage décale les données contenues dans le DataFrame d'une unité et les compare avec le rapport du jour précédent pour déterminer la croix d'or et la croix morte.
    
    #Acheter et vendre une partie de génération de signal
    
    buy_sig = vol_golden
    sell_sig =  vol_dead 

    #market_Créez un bloc de données appelé sig qui contient tous les 0
    market_sig = pd.DataFrame(data=0.0, columns=syms, index=dates)
    
    #buy_1 quand sig est vrai.0、sell_Quand sig est vrai-1.Mettre à 0
    market_sig[buy_sig == True] = 1.0
    market_sig[sell_sig == True] = -1.0
    market_sig[(buy_sig == True) & (sell_sig == True)] = 0.0
    # ctx.logger.debug(market_sig)

    return {
      "mav5:g2": mav5,
      "mav25:g2": mav25,
      "market:sig": market_sig,
    }

  #Enregistrement du signal
  ctx.regist_signal("my_signal", _my_signal)

def handle_signals(ctx, date, current):  #Partie de traitement quotidien
  '''
  current: pd.DataFrame
  '''
  #initialiser_my_Commercialiser le signal généré par le signal_Magasin dans sig
  market_sig = current["market:sig"]
  done_syms = set([])  #Type de set qui stocke les stocks pour lesquels le règlement des bénéfices et la réduction des pertes ont été effectués
  none_syms = set([])  # portfolio.Définissez le type qui stocke les marques qui n'existent pas dans des positions
  # portfolio.positions(Marques que vous possédez)Actions cibles(sym)Vérifiez s'il y a
  for (sym, val) in market_sig.items():
    if sym not in ctx.portfolio.positions:
      none_syms.add(sym)
  # portfolio.positions(Marques que vous possédez)Chaque marque de(sym)Vérifiez si le nombre d'actions détenues par
  for (sym, val) in ctx.portfolio.positions.items():
    if val["amount"] == 0:
      none_syms.add(sym)
  #Réduction des pertes, règlement des bénéfices(Rentabilité)paramètres de
  #Processus itératif pour vérifier les stocks que vous possédez un par un
  for (sym, val) in ctx.portfolio.positions.items():
    #Acquisition du ratio profit / perte
    returns = val["returns"]
    if returns < -0.03:  #Ratio profit / perte-3%Moins que(Valeur absolue 3%Plus grande perte)dans le cas de
      #Ordre de vente pour réduction des pertes
      sec = ctx.getSecurity(sym)
      sec.order(-val["amount"], comment="Coupe de perte(%f)" % returns)
      #Ajout du problème affecté à sym au type d'ensemble qui stocke le problème pour lequel le règlement des bénéfices et la réduction des pertes ont été effectués.
      done_syms.add(sym)
    elif returns > 0.05:  #Ratio profit / perte+5%Si supérieur à
      #Prise de bénéfices(Rentabilité)Ordre de vente pour
      sec = ctx.getSecurity(sym)
      sec.order(-val["amount"], comment="Vente à but lucratif(%f)" % returns)
      #Ajout du problème affecté à sym au type d'ensemble qui stocke le problème pour lequel le règlement des bénéfices et la réduction des pertes ont été effectués.
      done_syms.add(sym)
  buy = market_sig[market_sig > 0.0]  #Acheter signal
  for (sym, val) in buy.items():  #Traitez les actions avec les signaux d'achat un par un
    # done_syms ou aucun_Si syms a sym
    if sym in done_syms:
      continue  #Ignorer le traitement
    #Acheter la commande
    sec = ctx.getSecurity(sym)
    sec.order(sec.unit() * 1, orderType=ot, comment="SIGNAL BUY")
    #Si vous souhaitez afficher le journal des commandes d'achat ci-dessous, veuillez supprimer les commentaires ci-dessous(Attention à long terme)
    #ctx.logger.debug("BUY: %s,  %f" % (sec.code(), val))
  sell = market_sig[market_sig < 0.0]  #Signal de vente
  for (sym, val) in sell.items():  #Traitez les actions avec les signaux de vente un par un
    # done_syms ou aucun_Si syms a sym
    if (sym in done_syms) | (sym in none_syms):
      continue  #Ignorer le traitement
    #Ordre de vente
    sec = ctx.getSecurity(sym)
    sec.order(sec.unit() * -1,orderType=ot, comment="SIGNAL SELL")
  • Le code complété est ici
  • Les détails de l'algorithme sont décrits dans les commentaires sur chaque ligne.

résultat

alt

Évaluation / considération

  • Le rapport Sharp (efficacité de l'investissement) est raisonnablement bon ――Le ratio de profits et pertes sur un an est également excellent à 18% ――Si vous regardez des actions individuelles, vous pouvez être vulnérable à une forte baisse ou à une forte hausse. --Exemple: évolution des prix de Takeda Pharmaceutical Industry du 18 février 2019 au 18 février 2020 alt

À la fin

Au cours des trois dernières semaines, j'ai beaucoup appris sur la façon de développer des algorithmes de base avec QuantX Factory! À l'avenir, j'aimerais encore améliorer la qualité de l'algorithme en combinant la ligne moyenne mobile du volume avec d'autres indicateurs techniques et en incorporant l'apprentissage automatique. Cela conclut cet article. Merci d'avoir lu le pauvre texte jusqu'au bout!

Clause de non-responsabilité Précautions

Veuillez noter que nous ne sommes pas responsables des profits ou des pertes causés par des transactions réelles utilisant ce code / cette connaissance.

materials https://qiita.com/Miku_F/items/49c20fcbbbfae59cb9a6

https://www.kabutore.biz/idoheikinsen.html

https://ib-college.com/idou-heikin

Recommended Posts