
Il existe un nombre impressionnant de stratégies open source sur TradingView. Il est dommage que tant d’excellentes stratégies, idées et indicateurs ne puissent pas être mis en pratique. Voyant cela, FMZ, qui s’engage à populariser la technologie de trading quantitatif auprès de nombreux traders, ne peut naturellement pas réprimer l’envie de résoudre cette demande !
Cette demande est absolument insupportable !
Ainsi, dans le monde du code de programmation, j’ai voyagé à travers des montagnes et des rivières et j’ai vécu 9*9=81 pit, après avoir enduré d’innombrables nuits blanches, une montagne de canettes de Red Bull vides empilées dans le coin. Enfin, FMZ prend en charge et est compatible avec le langage Pine, et divers scripts TradingView Pine peuvent être utilisés.
En parlant du langage des pins, je ne l’ai appris que récemment par moi-même. Mais pour être honnête, le langage Pine pour le trading quantitatif est vraiment simple, facile à utiliser et facile à apprendre. Quoi? Vous n’y croyez pas ? Regardez-moi écrire une stratégie de grille pour vous~
/*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="间距价格")
var dir = input.string("long", title="方向", options = ["long", "short", "both"])
var amount = input.float(-1, title="下单量")
var numbers = input.int(-1, title="网格数量")
var profit = input.int(-1, title="盈利价差") / syminfo.mintick
if spacing == -1 and amount == -1 and numbers == -1 and profit == -1
runtime.error("参数错误")
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
// 实时K线阶段
if not barstate.ishistory
// 检索网格
for i = 1 to numbers
// 做多
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)
// 做空
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)
Le trading en temps réel de FMZ, les outils de backtesting, les nombreuses fonctions et la facilité d’utilisation du langage Pine, c’est comme ajouter des ailes à un tigre ! En incluant les paramètres et les codes de configuration des backtests, le nombre total de codes ne dépasse pas 50 lignes. Les débutants n’ont plus à se soucier d’écrire une grille…
Bien entendu, cette stratégie est une stratégie de grille. Les stratégies de grille ont aussi leurs défauts et ne constituent pas une machine à imprimer de l’argent garantie. La clé réside dans son utilisation et ses paramètres. Je ne vais pas m’étendre sur ce point. Concentrons-nous plutôt sur la façon d’écrire facilement des stratégies, de mettre en œuvre votre propre logique de trading et de gagner de l’argent en écrivant vos propres stratégies. C’est tellement agréable sans demander de l’aide à qui que ce soit ! !
Laissez-moi vous expliquer, le code est simple et facile à comprendre. Si vous ne parvenez toujours pas à écrire des stratégies en utilisant le langage Pine, facile à apprendre et à utiliser, alors je le ferai…….. ……… ……………………Laissez-moi vous raconter en détail !
Au début/*backtestet*/Le contenu enveloppé est le code de configuration du backtest FMZ, qui est la fonction de FMZ, pas le contenu du langage Pine. Bien entendu, vous pouvez choisir de ne pas écrire cette partie. Lors du backtesting, vous devrez cliquer manuellement sur les contrôles de paramètres pour définir la configuration et les paramètres du backtest.
/*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="间距价格")
var dir = input.string("long", title="方向", options = ["long", "short", "both"])
var amount = input.float(-1, title="下单量")
var numbers = input.int(-1, title="网格数量")
var profit = input.int(-1, title="盈利点数") / syminfo.mintick
strategy(overlay=true): Utilisé pour définir certaines options du script, overlay=true, qui consiste à donner des paramètresoverlayAttribuez une valeur vraie pour dessiner l’image sur l’image principale du graphique (le graphique K-line est l’image principale, il peut être compris aussi simplement que cela).varip beginPrice = 0:Une variable beginPrice est déclarée à l’aide du mot-clé varip et se voit initialement attribuer une valeur de 0, qui est utilisée comme prix initial de la grille.var spacing = input.float(-1, title="间距价格"): Définissez un paramètre de stratégie. Le nom du paramètre est « prix d’intervalle », qui correspond à l’intervalle entre chaque point de la grille. S’il est défini sur 100, cela signifie qu’une transaction sera effectuée chaque fois que le prix dépassera 100.var dir = input.string("long", title="方向", options = ["long", "short", "both"]):Un paramètre de stratégie est défini, nommé « direction ». Ce paramètre est une option avec une liste déroulante et vous pouvez choisir long, short ou les deux. Ils indiquent respectivement que la grille négocie uniquement à long terme, uniquement à court terme ou à la fois à long terme et à court terme.var amount = input.float(-1, title="下单量"): Définissez un paramètre pour contrôler le volume de transaction à chaque transaction de point de grille.var numbers = input.int(-1, title="网格数量"): Le nombre de points de grille. Le définir sur 20 signifie qu’il y a 20 points de grille dans une direction.var profit = input.int(-1, title="盈利价差") / syminfo.mintick: Définissez un paramètre pour contrôler la différence de prix à laquelle la position à chaque point de la grille sera fermée.Ensuite, regardez le code :
if spacing == -1 and amount == -1 and numbers == -1 and profit == -1
runtime.error("参数错误")
Cela signifie que si l’un des paramètres tels que l’espacement, le montant, les nombres et le profit n’est pas défini, la valeur par défaut est -1, ce qui signifie que la stratégie s’arrêtera (vous ne pouvez pas courir sans définir de paramètres ~ haha !)
Go on !
if not barstate.ishistory and beginPrice == 0
beginPrice := close
Cela signifie que lorsque la stratégie est dans la phase K-line en temps réel et que beginPrice == 0, modifiez la valeur de beginPrice au dernier prix actuel. On peut comprendre que lorsque la stratégie est officiellement en cours d’exécution, le prix initial actuel est le prix initial de la grille. Étant donné que le script comporte une étape BAR historique de type K-line, la stratégie exécutera la logique dans l’étape BAR historique. Il est tout à fait inutile d’organiser la grille sur la BAR historique.
Qu’est-ce que la phase BAR historique ?
Pour donner un exemple simple, à l’instant A, la stratégie commence à s’exécuter et obtient des données avec 100 BAR de ligne K. Au fil du temps, les 100 BAR deviendront certainement 101, 102… N. À partir du temps A, la 101e BAR est l’étape de la ligne K en temps réel, qui correspond aux dernières données en temps réel. Ainsi, de la 1ère BARRE à la 100ème BARRE, ce sont toutes des conditions de marché historiques qui sont passées, mais la stratégie sera également exécutée sur la base de ces conditions de marché historiques, donc cette étape est l’étape historique de la ligne K.
barstate.ishistoryIl s’agit d’une variable intégrée au langage Pine. Si la BAR actuelle est une BAR historique,barstate.ishistorySi ce n’est pas une BAR historique, c’est faux. Par conséquent, lorsque barstate.ishistory n’est pas vrai, il est dans l’étape de la ligne K en temps réel.
Ensuite, nous avons créé une fonction
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
La fonction de cette fonction est de déterminer si un certain ID existe dans toutes les commandes actuellement ouvertes. S’il existe, la fonction findTradeId renverra l’ID de la commande existante lorsqu’elle sera appelée (notez que cet ID n’est pas l’ID de la commande de l’échange, mais l’ID attribué à l’ordre par la stratégie). , ou interprété comme un label), s’il n’existe pas, renvoie la chaîne “notFound”.
Ensuite, nous commençons la feuille de maillage :
// 实时K线阶段
if not barstate.ishistory
// 检索网格
for i = 1 to numbers
// 做多
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)
// 做空
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)
Une boucle for est utilisée pour déterminer le nombre de boucles en fonction de la valeur du paramètre nombres, c’est-à-dire pour organiser le nombre de commandes correspondant. Définissez la direction en fonction du paramètre dir. Utilisez la fonction findTradeId pour savoir si la commande de l’étiquette à la position actuelle de la grille a été ouverte. Ne placez un ordre planifié que s’il n’a pas été ouvert (si c’est le cas, vous ne pouvez pas placer un ordre en double). Lorsque vous passez une commande, utilisez la fonction strategy.order pour spécifier le paramètre de limite afin de passer une commande planifiée. Passez l’ordre de clôture correspondant en même temps que vous passez l’ordre de plan. Pour fermer une position, utilisez la fonction strategy.exit, spécifiez le paramètre de profit et spécifiez les points de profit.




En observant simplement la courbe de rendement, on peut constater que le réseau comporte également des risques et qu’il n’est pas garanti que le succès soit au rendez-vous. C’est juste que le risque est relativement moindre lorsque le réseau est élargi à grande échelle.
Eh bien, si vous ne parvenez toujours pas à écrire des stratégies en utilisant le langage Pine, facile à apprendre et à utiliser, alors je…