
Dans cet article, nous allons créer un bot de trading de grille en Python à l’aide de l’API Alpaca Trading. Un bot de trading de grille est un bot qui exécutera des ordres d’achat et de vente d’un titre en fonction de niveaux prédéterminés. Contrairement à la plupart des autres stratégies de trading, ces niveaux n’ont généralement rien à voir avec l’évolution des prix ou l’analyse technique. La logique principale derrière l’algorithme est la façon dont ces niveaux sont déterminés en fonction du cours de clôture le plus récent.
Le lien vers le référentiel GitHub est ci-dessous pour ceux qui souhaitent suivre.
Disons par exemple que nous voulions mettre en place une stratégie de trading en grille pour ETHUSD. La première chose que nous devrions faire est d’obtenir le prix actuel de l’actif, puis de déterminer le nombre de lignes de grille que nous aurons ainsi que l’espace entre ces lignes de grille. Plus il y a de lignes de grille et plus ces lignes sont proches les unes des autres, plus le bot exécutera de transactions. Alors que moins de lignes de grille avec des écarts plus grands exécuteront moins de transactions. L’exemple ci-dessous aura un nombre de lignes de grille de 3 avec un espace de 5 graduations entre chaque ligne de grille. Lorsque le prix atteint les lignes supérieures de la grille, le bot vendra des fractions de la position actuelle, lorsque le prix atteint les lignes inférieures de la grille, le bot achètera plus d’actions du courant
Voir ci-dessous pour l’exemple

Pour ce didacticiel, nous établirons des lignes de grille à un espace de 100 et un nombre de 5. Cela signifie que nous aurons 5 lignes de grille avec un espace de 100 entre chaque ligne.
from websocket import create_connection
import simplejson as json
from secret import Secret
import pandas as pdclass Stream_Data:
def __init__(self) -> None: self.url = 'wss://stream.data.alpaca.markets/v1beta1/crypto?exchanges=CBSE' def bar_data(self):
ws = create_connection(self.url) auth_message = {"action":"auth","key": Secret.paper_api_key, "secret": Secret.paper_secret_key}ws.send(json.dumps(auth_message))
subscription = {"action":"subscribe","bars":["ETHUSD"]}
while True:
ws.send(json.dumps(subscription))
data = json.loads(ws.recv())
yield data[0]
Le code ci-dessus est stocké dans le fichier stream_data.py, ce script diffusera des données cryptographiques en temps réel à l’aide d’alpaca websockets. Après avoir importé nos bibliothèques et créé notre classe « Stream_Data », nous créons une connexion appelée url dans notre constructeur. Cette connexion est ce que nous utiliserons pour diffuser des données cryptographiques en temps réel pour notre échange. La connexion est appelée à nouveau dans la méthode « bar_data », nous créons d’abord notre connexion avec la méthode « create_connection » et la stockons dans la variable websocket ws. Après avoir établi une connexion, nous devons maintenant envoyer notre message d’authentification à notre serveur Web. Ce message « auth_message » contient nos clés API dans un objet json, les vidages json formateront les données dans une chaîne json juste avant de les envoyer au serveur Tye en utilisant « ws.send ({chaîne json insérée ici}) ». Après la connexion au serveur, nous nous abonnerons à nos données Ethereum en utilisant la même méthode que notre message d’authentification. Après vous être connecté et vous être abonné à notre flux de données, nous recevrons nos données en utilisant « ws.recv() ». Nous avons alors une boucle infinie qui renverra les données de la barre en temps réel au format json avec « yield data[0]”.
Dans notre prochain fichier « rules.py », nous créons les paramètres de base pour notre bot de grille. Dans la méthode « calculate_grid_lines », nous calculons le nombre de lignes de grille, l’espace entre les lignes de grille, le take profit et le stop loss. Dans ce cas, nous avons 5 lignes de grille au-dessus de notre prix de clôture actuel et 5 lignes de grille en dessous de ce même prix. Il y a 100 graduations entre chacune de ces lignes de grille. Les niveaux de prise de profit et de stop loss agissent en quelque sorte comme la 6ème ligne de grille pour le prix. La principale différence entre ces niveaux et les lignes de la grille est qu’une fois que le prix atteint le take profit ou le stop loss, il vend bien la totalité de la position plutôt que des ventes partielles. Ceci sera discuté plus en détail dans la prochaine section de l’article.
Dans notre méthode suivante « calculate_position_size », nous déterminons quelle est la meilleure taille de position pour gérer notre risque. Dans le commentaire ci-dessus, nous ne voulons pas risquer plus de 10 % de notre compte, donc lorsque notre stop loss est déclenché, nous devrions avoir une perte maximale de seulement 10 % du solde de notre compte. Cela se fait en prenant d’abord 10% de la taille de notre compte et en le stockant dans la variable « risque ». Nous déterminons ensuite nos « ticks_at_risk » en multipliant le nombre de lignes de grille que nous utilisons par l’espace entre chaque grille. Notre « position_size » est déterminé en divisant le « risque » par le produit des « ticks-at_risk » et de la « tick_value ». Cette stratégie de base de gestion des risques aide à empêcher le bot de faire exploser le compte après une seule journée de trading.
class Rules:
def __init__(self, current_price) -> None:
self.line_count = 5
self.grid_space = 100
self.current_price = current_pricedef calculate_grid_lines(self):
line_count = self.line_count
grid_space = self.grid_space
price = self.current_price
stop_loss = price - ((line_count + 1) * grid_space)
take_profit = price + ((line_count + 1) * grid_space)
buy_lines = []
sell_lines = []
for i in range(line_count):
buy_lines.append(price - ((line_count * grid_space)))
sell_lines.append(price + ((line_count * grid_space)))
return stop_loss, take_profit, buy_lines, sell_lines
# risk no more than 10 percent of our account on a single trade
# when the stoploss is triggered we should only lose 10 percent
def calculate_position_size(self, account_size):
line_count = self.line_count
grid_space = self.grid_space
risk = account_size * .1
tick_value = 1
ticks_at_risk = (line_count + 1) * grid_space
position_size = risk / (ticks_at_risk * tick_value)
position_size = round(position_size, 2)
return position_size
Après avoir importé nos bibliothèques nécessaires et nos scripts personnalisés « rules.py », « stream_data.py » et « secret.py ». Nous avons ensuite configuré notre connexion API avec nos clés API dans notre constructeur. Après cela, notre méthode suivante « current_profit_loss » est utilisée pour calculer le profit/perte actuel sur notre compte, cela sera utilisé pour s’assurer que notre algorithme fonctionne bien. La viande du code est stockée dans « start_bot() », c’est là que le bot exécutera les ordres d’achat et de vente en fonction de la proximité du prix par rapport aux lignes de la grille. Tout d’abord, notre méthode « start_bot() » exécutera un ordre d’achat au début de la session, puis nous obtiendrons le pouvoir d’achat disponible de notre compte. Nous l’utilisons ensuite pour calculer la taille de notre position en utilisant la méthode appropriée dans notre « rules.py ». Après avoir soumis notre ordre d’achat et configuré nos lignes de grille, nous parcourons ensuite toutes les données de la barre qui sont diffusées en continu et si le prix de clôture de l’une des barres figure dans notre liste de « lignes d’achat » renvoyée, nous exécutons un achat partiel. De même, si l’une des barres se trouve dans notre tableau « sell_lines » renvoyé, nous exécuterons une vente partielle. Si le cours de clôture atteint la dernière ligne de grille de « take_profit » ou « stop_loss », nous fermerons toutes les positions et appellerons récursivement « start_bot() », et l’algorithme recommencera depuis le début avec le dernier cours de clôture.
import alpaca_trade_api as tradeapi
from more_itertools import first
from stream_data import Stream_Data as stream
from secret import Secret
import numpy as np
import pandas as pd
from pprint import pprint
from rules import Rulesclass Bot:
def __init__(self):
api_key = Secret.paper_api_key
secret_key = Secret.paper_secret_key
alp_base_url = 'https://paper-api.alpaca.markets'
api = tradeapi.REST(api_key, secret_key, alp_base_url, api_version='v2')
self.data_url = 'https://data.alpaca.markets/v1beta1/crypto'
self.header = {
'APCA-API-KEY-ID' : Secret.paper_api_key,
'APCA-API-SECRET-KEY' : Secret.paper_secret_key}
self.api_key = api_key
self.secret_key = secret_key
self.api = apidef current_profit_loss(self):
def start_bot(self):
api = self.api
account = api.get_account()
# Check our current balance vs. our balance at the last market close
balance_change = float(account.equity) - float(account.last_equity)
print(f'Today\'s portfolio balance change: ${balance_change}')
api = self.api
s = stream()
bars = s.bar_data()# initial buy
for _ in range(3):
print(next(bars))first_close = next(bars)['c']
# position size is the total amount of our account that we are risking
r = Rules(first_close)
account = api.get_account()
available_funds = int(account.buying_power)
print(available_funds)
position_size =
r.calculate_position_size(account_size=available_funds)
print('position_size {}'.format(position_size))
# the amount of the position we buy or sell off at each line
partial_position = position_size / 7
print('First Purchase of {} at {}'.format(position_size, first_close))
api.submit_order(
symbol='ETHUSD',
side='buy',
type='market',
qty=position_size,
)# set up grid lines
stop_loss, take_profit, buy_lines, sell_lines = r.calculate_grid_lines()for bar in bars:
close = bar['c']
if close in buy_lines:
api.submit_order(
symbol='ETHUSD',
side='buy',
type='market',
qty=partial_position,
)
if close in sell_lines:
api.submit_order(
symbol='ETHUSD',
side='sell',
type='market',
qty=partial_position,
)if take_profit == close:
if __name__ == '__main__':
print('exit all positions at profit')
api.close_all_positions()
b.current_profit_loss()
b.start_bot()
if stop_loss == close:
print('exit all positions at a loss')
api.close_all_positions()
b.current_profit_loss()
b.start_bot()
b = Bot()
b.start_bot()
Ce bot est conçu pour acheter et vendre sur la base de lignes de grille centrées autour du cours de clôture actuel. Lorsque le prix atteint un extrême (les niveaux de prise de profit ou de stop loss), le bot quittera toutes les positions et recommencera au cours de clôture actuel.
Rejoignez Coinmonks Telegram Channel et Youtube Channel pour en savoir plus sur le trading et l’investissement cryptographiques