
En TradingView hay una cantidad abrumadora de estrategias de código abierto. Es una lástima que no se puedan poner en práctica tantas estrategias, ideas e indicadores excelentes. Al ver esto, FMZ, que está comprometido a popularizar la tecnología de comercio cuantitativo para muchos comerciantes, ¡naturalmente no puede reprimir el impulso de resolver esta demanda!
¡Esta exigencia es absolutamente insoportable!
Entonces, en el mundo del código de programación, viajé a través de montañas y ríos, y experimenté 9*9=81 boxes, después de soportar incontables noches de insomnio, una montaña de latas de Red Bull vacías se amontonaron en la esquina. Finalmente, FMZ soporta y es compatible con el lenguaje Pine, y se pueden utilizar varios scripts Pine de TradingView.
Hablando del lenguaje Pine, recién lo aprendí por mi cuenta hace poco. Pero para ser honesto, el lenguaje Pine para el trading cuantitativo es realmente simple, fácil de usar y fácil de aprender. ¿Qué? ¿No lo crees? Mírame escribiendo una estrategia de cuadrícula para ti~
/*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)
¡El trading en tiempo real de FMZ, las herramientas de backtesting, las numerosas funciones y la facilidad de uso del lenguaje Pine son como agregarle alas a un tigre! Incluyendo configuraciones de parámetros y códigos de configuración de backtest, el número total de códigos no excede las 50 líneas. Los principiantes ya no tienen que preocuparse por escribir una cuadrícula…
Por supuesto, esta estrategia es una estrategia de cuadrícula. Las estrategias de cuadrícula también tienen sus defectos y no es una máquina de imprimir dinero garantizada. La clave está en su uso y sus parámetros. No me extenderé en este punto. Centrémonos más en cómo escribir estrategias fácilmente, implementar tu propia lógica de trading y ganar dinero escribiendo tus propias estrategias. ¡Se siente tan bien no tener que pedirle ayuda a nadie! !
Déjame explicarte, el código es simple y fácil de entender. Si aún no puedes escribir estrategias usando el lenguaje Pine, fácil de aprender y usar, entonces yo lo haré… ……… …………………….¡Déjame contártelo en detalle!
Al principio/*backtesty*/El contenido envuelto es el código de configuración de backtest de FMZ, que es la función de FMZ, no el contenido del lenguaje Pine. Por supuesto, puede optar por no escribir esta parte. Al realizar pruebas retrospectivas, deberá hacer clic manualmente en los controles de parámetros para establecer la configuración y los parámetros de las pruebas retrospectivas.
/*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]]
*/
El siguiente código:
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):Se utiliza para establecer algunas opciones del script, overlay=true, que sirve para dar parámetrosoverlayAsigne un valor de verdadero para dibujar la imagen en la imagen principal del gráfico (el gráfico de línea K es la imagen principal, se puede entender tan simple como esto).varip beginPrice = 0:Una variable beginPrice se declara usando la palabra clave varip y se le asigna inicialmente un valor de 0, que se utiliza como el precio inicial de la cuadrícula.var spacing = input.float(-1, title="间距价格"): Establezca un parámetro de estrategia. El nombre del parámetro es “precio de intervalo”, que es el intervalo entre cada punto de la cuadrícula. Si se establece en 100, significa que se realizará una transacción cada vez que el precio supere 100.var dir = input.string("long", title="方向", options = ["long", "short", "both"]):Se establece un parámetro de estrategia denominado “dirección”. Este parámetro es una opción con un cuadro desplegable y se puede elegir entre largo, corto o ambos. Indican respectivamente que la red solo opera en posiciones largas, solo opera en posiciones cortas o opera tanto en posiciones largas como cortas.var amount = input.float(-1, title="下单量"):Establezca un parámetro para controlar el volumen de transacciones en cada punto de la cuadrícula.var numbers = input.int(-1, title="网格数量"): Número de puntos de la cuadrícula. Si se establece en 20, significa que hay 20 puntos de cuadrícula en una dirección.var profit = input.int(-1, title="盈利价差") / syminfo.mintick:Establezca un parámetro para controlar la diferencia de precio con la que se cerrará la posición en cada punto de la cuadrícula.A continuación, mira el código:
if spacing == -1 and amount == -1 and numbers == -1 and profit == -1
runtime.error("参数错误")
Esto significa que si alguno de los parámetros como espaciado, cantidad, números y ganancias no está configurado, el valor predeterminado es -1, lo que significa que la estrategia se detendrá (¡no puedes correr sin configurar parámetros ~ jaja!)
Go on !
if not barstate.ishistory and beginPrice == 0
beginPrice := close
Lo que esto significa es que cuando la estrategia está en la etapa de línea K en tiempo real y beginPrice == 0, modifique el valor de beginPrice al último precio actual. Se puede entender que cuando la estrategia está oficialmente en marcha, el precio actual inicial es el precio inicial de la red. Debido a que el script tiene una etapa BAR de línea K histórica, la estrategia ejecutará la lógica en la etapa BAR histórica. Definitivamente no tiene sentido organizar la cuadrícula en la etapa BAR histórica.
¿Qué es la Fase BAR Histórica?
Para dar un ejemplo sencillo, en el momento actual A, la estrategia empieza a ejecutarse y la estrategia obtiene datos con 100 BAR de la línea K. A medida que pasa el tiempo, los 100 BAR se convertirán definitivamente en 101, 102… N. Cuando se ejecuta desde el tiempo A, la BARRA 101 es la etapa de la línea K en tiempo real, que son los últimos datos en tiempo real. Entonces, desde la 1.ª BARRA hasta la 100.ª BARRA, todas estas son condiciones históricas del mercado que han pasado, pero la estrategia también se ejecutará en estas condiciones históricas del mercado, por lo que esta etapa es la etapa histórica de la línea K.
barstate.ishistoryEsta es una variable incorporada del lenguaje Pine. Si la BAR actual es una BAR histórica,barstate.ishistorySi no es un BAR histórico es falso. Por lo tanto, cuando no barstate.ishistory es verdadero, está en la etapa de línea K en tiempo real.
A continuación, creamos una función
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 función de esta función es averiguar si existe un ID determinado en todas las órdenes abiertas actualmente. Si existe, la función findTradeId devolverá el ID de la orden existente cuando se la llame (tenga en cuenta que este ID no es el ID de la orden de el intercambio, pero el ID asignado a la orden por la estrategia). , o interpretado como una etiqueta), si no existe, devuelve la cadena “notFound”.
A continuación, comenzamos la lámina de malla:
// 实时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)
Un bucle for se utiliza para determinar el número de bucles en función del valor del parámetro números, es decir, para organizar el número correspondiente de órdenes. Establezca la dirección según el parámetro dir. Utilice la función findTradeId para averiguar si se ha abierto el pedido de la etiqueta en la posición actual de la cuadrícula. Coloque un pedido planificado solo si no se ha abierto (si se ha abierto, no puede colocar un pedido duplicado). Al realizar un pedido, utilice la función strategy.order para especificar el parámetro límite para realizar un pedido planificado. Coloque la orden de cierre correspondiente al mismo tiempo que coloca la orden planificada. Para cerrar una posición, utilice la función strategy.exit, especifique el parámetro de beneficio y especifique los puntos de beneficio.




Con solo observar la curva de rendimiento, se puede ver que la red también tiene riesgos y no es una garantía de ganancias. Simplemente, el riesgo es relativamente menor cuando la red se amplía a gran escala.
Bueno, si todavía no puedes escribir estrategias usando el lenguaje Pine, fácil de aprender y de usar, entonces yo…