TradingView上的开源策略数量多到爆炸,这么多优秀的策略、思路、指标不能实盘真是太可惜了。看到这一点,作为致力于把量化交易技术普及给众多交易者的FMZ自然不能抑制这种解决需求的冲动!
这个需求绝对不能忍!
于是,在编程开发的代码世界里跋山涉水、走过万水千山,历经9*9=81坑,熬过无数个不眠的夜晚,墙角堆砌起了小山一般的红牛空罐子之后。终于FMZ支持兼容了Pine语言,各种TradingView的Pine脚本都可以拿来用了。
说到Pine语言,小编我也是最近才自学。不过说实话作为量化交易的Pine语言真的是简单易用,易学。 什么?不信?看我洋洋洒洒给你写个网格策略~
/*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)
FMZ的实盘、回测工具、众多的功能再加上Pine语言的简单易用,可算如虎添翼!算上参数设置、回测配置代码,总共代码也没超过50行。入门的同学再也不用为了写个网格头疼到炸了。。。
当然啦,这个策略是个网格策略,网格策略也有硬伤,也不是包赢的印钞机,关键看用法、参数。这点就不赘述了,我们更多来关注如何轻松的写策略,实现自己的交易逻辑,自己写策略交易赚钱,不求人的感觉太爽了!!
我来给各位看官讲解讲解,代码简单易懂,用这么易学易用的Pine语言如果还不会写策略的话,那我就…详细的给您讲讲!
开头的/*backtest
和*/
包裹住的内容是FMZ的回测配置代码,这个是FMZ的功能,并非Pine语言的内容。当然,您可以不写这部分内容,回测的时候就需要手动点击参数控件来设置回测配置和参数了。
/*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
strategy(overlay=true)
: 用来设置脚本的一些选项,overlay=true,就是给参数overlay
赋值true,让画图时,画在图表的主图上(K线图就是主图,可以这么简单理解)。varip beginPrice = 0
: 用关键字varip声明了一个变量beginPrice初始赋值为0,这个值是用作网格的初始价格。var spacing = input.float(-1, title="间距价格")
: 设置一个策略参数,参数名字叫“间距价格”,就是每个网格点的间距,设置100就是价格每过100,交易一次。var dir = input.string("long", title="方向", options = ["long", "short", "both"])
: 设置了一个策略参数,名字叫“方向”,这个参数是一个带下拉框的选项,可以选择long,short,both。分别表示网格只做多、只做空、多空都做。var amount = input.float(-1, title="下单量")
: 设置一个参数,用来控制每次网格点交易时的交易量。var numbers = input.int(-1, title="网格数量")
: 网格点的数量,设置20就是一个方向20个网格点。var profit = input.int(-1, title="盈利价差") / syminfo.mintick
: 设置一个参数,控制每个网格点的持仓盈利到多少价差就平仓。接下来,看代码:
if spacing == -1 and amount == -1 and numbers == -1 and profit == -1
runtime.error("参数错误")
意思就是如果spacing、amount、numbers、profit这些参数任何没有设置的话,默认是-1,就让策略停止(没设置参数不能瞎跑~哈哈!)
Go on !
if not barstate.ishistory and beginPrice == 0
beginPrice := close
这里的意思就是当策略处于实时K线阶段并且beginPrice == 0 时,去给beginPrice修改值,改为当前的最新价格。可以理解为策略正式运行时,初始当前价格为网格的初始价格。因为脚本是有历史K线BAR阶段的,策略在历史BAR阶段会执行一遍逻辑,历史BAR上去布置网格肯定是没什么意义。
什么是历史BAR阶段?
简单举个例子,比如当前时刻A,策略开始运行,策略拿到了一个有100个K线BAR的数据,随着时间肯定是100个BAR变成101个,102个… N个。从A时刻开始运行时,第101个BAR就是实时K线阶段了,这个时候是最新的实时数据了。那么从第1个BAR到第100个BAR,这些都是已经过去的历史行情了,但是策略也会在这些历史行情上运行一遍,所以这个阶段就是历史K线阶段。
barstate.ishistory
这个是Pine语言的一个内置变量,如果当前的BAR是历史阶段的BAR,barstate.ishistory
就为true,如果不是历史阶段的BAR就为false。所以 not barstate.ishistory 为true时,就是处于实时K线阶段了。
接下来,我们创建了一个函数
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
这个函数的作用就是在当前已经开仓的所有订单中查找某个id是否存在,如果存在findTradeId函数调用时就返回存在的单子的ID(注意这个ID不是交易所的订单ID,是策略给订单起的名字或者理解为标签),如果不存在就返回字符串"notFound"。
接下来就开始网格布单了:
// 实时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)
使用了for循环,根据numbers参数的数值,确定循环次数,即布置对应个数的订单。根据dir参数,设置direction。使用findTradeId函数查找当前网格位置的标签的订单是否已经开仓,只有没有开仓时才去下计划单(开仓了肯定就不能重复下了)。下单使用strategy.order函数指定limit参数做计划单。下计划单的同时下对应的平仓单。平仓单使用strategy.exit函数,指定profit参数,指定利润点数。
看收益曲线就知道,网格也是有风险的,并非包赢,只不过在一个大尺度上拉大网格相对风险小了一点而已。
那么,用这么易学易用的Pine语言如果还不会写策略的话,那我就…
Stalker 这种胎教级别的教程能不能多来几个,最好专门来个pine的教程(知识付费)hhh 。梦总v587
artron 谢谢
bbbwwed2009 梦总V5
发明者量化-小小梦 有的,在B站已经做了一个系列的Pine教程了:https://www.bilibili.com/video/BV1sU4y1B71i/
发明者量化-小小梦 不客气,感谢支持FMZ。
发明者量化-小小梦 B站上有PINE语言入门视频也可以看。