Le nombre de stratégies open source sur TradingView est grand. Il est dommage que tant d'excellentes stratégies, idées et indicateurs ne puissent pas être utilisés dans un vrai bot. Voyant cela, FMZ, qui s'engage à populariser la technologie de trading quantitative auprès de nombreux traders, ne peut naturellement pas supprimer cette envie de résoudre le problème!
Ce partage d'expérience est absolument à offrir!
Ainsi, après avoir parcouru le monde de la programmation et du développement de code, traversé 9*9=81 fosses, survécu à d'innombrables nuits blanches, et empilé une montagne de canettes vides de Red Bull dans un coin.
En ce qui concerne le langage Pine, je ne me suis appris que récemment. Mais pour être honnête, le langage Pine pour le trading quantitatif est vraiment facile à utiliser et facile à apprendre. Laissez-moi vous écrire une stratégie de grille:
/*backtest
start: 2021-06-01 00:00:00
end: 2022-05-23 00:00:00
period: 1h
basePeriod: 1m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
args: [["v_input_float_1",500],["v_input_string_1",2],["v_input_float_2",0.01],["v_input_int_1",20],["v_input_int_2",500],["RunMode",1,358374],["MinStock",0.001,358374]]
*/
strategy(overlay=true)
varip beginPrice = 0
var spacing = input.float(-1, title="Spacing prices")
var dir = input.string("long", title="Directions", options = ["long", "short", "both"])
var amount = input.float(-1, title="Order quantity")
var numbers = input.int(-1, title="Number of grids")
var profit = input.int(-1, title="Profit spreads") / syminfo.mintick
if spacing == -1 and amount == -1 and numbers == -1 and profit == -1
runtime.error("Parameter errors")
if not barstate.ishistory and beginPrice == 0
beginPrice := close
findTradeId(id) =>
ret = "notFound"
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == id
ret := strategy.opentrades.entry_id(i)
ret
// Real-time K-line stage
if not barstate.ishistory
// Retrieve grid
for i = 1 to numbers
// Going long
direction = dir == "both" ? "long" : dir
plot(beginPrice-i*spacing, direction+str.tostring(i), color.green)
if direction == "long" and beginPrice-i*spacing > 0 and beginPrice-i*spacing < close and findTradeId(direction+str.tostring(i)) == "notFound"
strategy.order(direction+str.tostring(i), strategy.long, qty=amount, limit=beginPrice-i*spacing)
strategy.exit("exit-"+direction+str.tostring(i), direction+str.tostring(i), qty_percent=100, profit=profit)
// Going short
direction := dir == "both" ? "short" : dir
plot(beginPrice+i*spacing, direction+str.tostring(i), color.red)
if direction == "short" and beginPrice+i*spacing > close and findTradeId(direction+str.tostring(i)) == "notFound"
strategy.order(direction+str.tostring(i), strategy.short, qty=amount, limit=beginPrice+i*spacing)
strategy.exit("exit-"+direction+str.tostring(i), direction+str.tostring(i), qty_percent=100, profit=profit)
FMZ
Bien sûr, cette stratégie est une stratégie de grille, qui a aussi des défauts, et ce n'est pas une machine d'impression d'argent qui gagne toujours. La clé dépend de l'utilisation et des paramètres. Nous allons nous concentrer davantage sur la façon d'écrire des stratégies facilement pour mettre en œuvre notre propre logique de trading, et gagner de l'argent en écrivant des stratégies et en négociant nous-mêmes. C'est tellement cool de ne pas demander de l'aide!
Je vais vous expliquer à tous, le code est simple et facile à comprendre, avec un tel langage facile à apprendre et à utiliser Pine, si vous ne pouvez toujours pas écrire une stratégie, alors je vais... vous dire en détail!
Le contenu de/*backtest
et*/
au début est le code de configuration de backtest de FMZ. C'est la fonction de FMZ, pas le contenu du langage Pine. Bien sûr, vous pouvez laisser cette partie de côté, et vous cliquerez sur le contrôle de paramètre manuellement pour définir la configuration de backtest et les paramètres pendant le backtesting.
/*backtest
start: 2021-06-01 00:00:00
end: 2022-05-23 00:00:00
period: 1h
basePeriod: 1m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
args: [["v_input_float_1",500],["v_input_string_1",2],["v_input_float_2",0.01],["v_input_int_1",20],["v_input_int_2",500],["RunMode",1,358374],["MinStock",0.001,358374]]
*/
Le code suivant:
strategy(overlay=true)
varip beginPrice = 0
var spacing = input.float(-1, title="Spacing prices")
var dir = input.string("long", title="Directions", options = ["long", "short", "both"])
var amount = input.float(-1, title="Order quantity")
var numbers = input.int(-1, title="Number of grids")
var profit = input.int(-1, title="Profit points") / syminfo.mintick
strategy(overlay=true)
: Il est utilisé pour définir certaines options du script, overlay=true, qui est d'attribuer une valeur vraie au paramètreoverlay
, de sorte que lors du dessin du graphique, il est dessiné sur le graphique principal (K-ligne graphique est le graphique principal, il peut être compris si simplement).varip beginPrice = 0
: Une variable beginPrice est déclarée avec le mot clé varip avec une valeur initiale de 0, qui est utilisée comme prix initial pour la grille.var spacing = input.float(-1, title="Spacing prices")
: Définir un paramètre de stratégie, le nom du paramètre est var dir = input.string("long", title="Directions", options = ["long", "short", "both"])
: Configurez un paramètre de stratégie nommé var amount = input.float(-1, title="Order quantity")
: définir un paramètre pour contrôler le volume des transactions à chaque transaction de point de réseau.var numbers = input.int(-1, title="Number of grids")
: le nombre de points de grille, en réglant 20 est de 20 points de grille dans un sens.var profit = input.int(-1, title="Profit spreads") / syminfo.mintick
: Définir un paramètre permettant de contrôler la marge bénéficiaire de chaque position de point de grille avant de fermer la position.Ensuite, regardez le code:
if spacing == -1 and amount == -1 and numbers == -1 and profit == -1
runtime.error("Parameter errors")
Cela signifie que si des paramètres tels que l'espacement, le montant, les chiffres et le profit ne sont pas définis, le défaut est -1, et la stratégie s'arrêtera (vous ne pouvez pas opérer à l'aveugle sans définir des paramètres)
Allez, allez!
if not barstate.ishistory and beginPrice == 0
beginPrice := close
Ce que cela signifie ici, c'est que lorsque la stratégie est à l'étape de la ligne K en temps réel et commencePrice == 0, changez la valeur de commencePrice au dernier prix actuel. On peut comprendre que lorsque la stratégie est officiellement en cours d'exécution, le prix actuel initial est le prix initial de la grille. Parce que le script a une étape BAR historique de la ligne K, la stratégie exécutera la logique une fois à l'étape BAR historique, et il est définitivement inutile d'organiser la grille sur la BAR historique.
Quelle est l'étape historique du BAR?
Pour donner un exemple simple, au moment actuel A, la stratégie commence à s'exécuter, et la stratégie obtient des données avec 100 K-line BARs. Au fil du temps, 100 BARs deviendront 101, 102...N. Quand elle commence à fonctionner à partir du moment A, la 101e BAR est l'étape de la ligne K en temps réel, et cette fois, ce sont les dernières données en temps réel. Ensuite, de la 1ère BAR à la 100e BAR, ce sont les prix historiques du marché qui sont passés, mais la stratégie fonctionnera également sur ces prix historiques du marché, donc cette étape est l'étape historique de la ligne K.
barstate.ishistory
c'est une variable intégrée dans le langage Pine,barstate.ishistory
est vrai si le BAR actuel est un BAR historique, et faux si ce n'est pas un BAR historique.
Ensuite, une fonction est créée
findTradeId(id) =>
ret = "notFound"
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == id
ret := strategy.opentrades.entry_id(i)
ret
Le rôle de cette fonction est de savoir si un certain id existe dans tous les ordres qui ont actuellement ouvert une position. S'il y a un appel à la fonction findTradeId, il renverra l'ID de l'ordre existant (notez que cet ID n'est pas l'ID d'ordre de l'échange, c'est le nom donné à l'ordre par la stratégie ou compris comme une étiquette), s'il n'existe pas, la chaîne
L'étape suivante consiste à démarrer la feuille de grille:
// Real-time K-line stage
if not barstate.ishistory
// Retrieve grid
for i = 1 to numbers
// Going long
direction = dir == "both" ? "long" : dir
plot(beginPrice-i*spacing, direction+str.tostring(i), color.green)
if direction == "long" and beginPrice-i*spacing > 0 and beginPrice-i*spacing < close and findTradeId(direction+str.tostring(i)) == "notFound"
strategy.order(direction+str.tostring(i), strategy.long, qty=amount, limit=beginPrice-i*spacing)
strategy.exit("exit-"+direction+str.tostring(i), direction+str.tostring(i), qty_percent=100, profit=profit)
// Going short
direction := dir == "both" ? "short" : dir
plot(beginPrice+i*spacing, direction+str.tostring(i), color.red)
if direction == "short" and beginPrice+i*spacing > close and findTradeId(direction+str.tostring(i)) == "notFound"
strategy.order(direction+str.tostring(i), strategy.short, qty=amount, limit=beginPrice+i*spacing)
strategy.exit("exit-"+direction+str.tostring(i), direction+str.tostring(i), qty_percent=100, profit=profit)
La boucle for est utilisée, et le nombre de boucles est déterminé en fonction de la valeur du paramètre des nombres, c'est-à-dire le nombre correspondant d'ordres sont disposés. Définir la direction en fonction du paramètre dir. Utilisez la fonction findTradeId pour savoir si l'ordre de l'étiquette à la position de la grille actuelle a été ouvert, et ne placez l'ordre prévu si il n'y a pas de position ouverte (si la position est ouverte, il ne peut pas être répété). Pour placer un ordre, utiliser la fonction strategy.order pour spécifier le paramètre limite comme un ordre prévu. Placer l'ordre de fermeture correspondant tout en plaçant l'ordre prévu. L'ordre de fermeture utilise lestrategy.exitfonction, spécifie le paramètre de profit, et spécifie les points de profit.
En regardant la courbe de profit, on voit que le réseau est aussi risqué. Ce n'est pas une victoire garantie. C'est juste que le risque d'expansion du réseau à grande échelle est un peu plus faible.
Si vous ne savez pas écrire une stratégie dans un langage aussi facile à apprendre et à utiliser, alors...