If you haven't written a strategy yet with Pine, which is so easy to learn, then I...

Author: The Little Dream, Created: 2022-06-01 17:37:55, Updated: 2023-09-18 20:19:45

img

If you haven't written a strategy yet with this easy-to-learn Pine language, then I...

It's a shame that so many great strategies, ideas, and indicators can't be implemented in TradingView. It's a shame that FMZ, as a company committed to making quantitative trading technology available to many traders, can't contain the urge to address this need!

This demand is absolutely unbearable!

So, in the world of programming development code, after climbing mountains, walking over thousands of mountains, going through 9*9=81 pits, sleepless nights, the corner of the wall piled up the typical red bull empty shell of the small mountain. Finally FMZ support is compatible with the Pine language, and all kinds of TradingView's Pine scripts can be used.

I've only recently started learning the language myself. The truth is, though, that the language used to quantify transactions is really simple and easy to learn. What? Don't believe it? Look at my onions writing you a grid strategy.

/*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's hard disk, retesting tools, numerous functions, plus the ease of use of the Pine language, can be counted as a tiger's wing!

Of course, this strategy is a grid strategy, the grid strategy also has a hard wound, not a win-win printing machine, the key is to see the use, parameters. This is not a summary, we are more focused on how easy it is to write strategies, realize your own trading logic, write strategies trading to make money, without asking people feel so cool!

Code explained

I'm here to explain to you, the code is simple and easy to understand, and if you haven't written a strategy yet in this easy to learn language, I'll... tell you in detail!

Starting with/*backtestand*/The enclosed content is FMZ's retest configuration code, which is a feature of FMZ, not the content of the Pine language. Of course, you can leave this part of the content unwritten, and manually click on the parameter control to set the retest configuration and parameters when retesting.

/*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]]
*/

The following code:

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)Some of the options used to set the script, overlay=true, is to give parameters:overlayAssign the value true, so that when drawing a graph, the graph is drawn on the main graph of the graph (the K line graph is the main graph, so it is easy to understand).
  • varip beginPrice = 0: The variable startPrice is declared with the keyword varip, and is assigned an initial value of 0, which is the initial price of the grid.
  • var spacing = input.float(-1, title="间距价格"): Set a policy parameter called the price interval interval interval, which is the interval of each grid point, set to 100, which is the price every 100 trades.
  • var dir = input.string("long", title="方向", options = ["long", "short", "both"]): Set a policy parameter, called the grid directional parameter, which is an option with a drag box that allows you to select long, short, or both.
  • var amount = input.float(-1, title="下单量"): Set a parameter to control the volume of transactions at each grid point.
  • var numbers = input.int(-1, title="网格数量"): the number of grid points, set to 20, is 20 grid points in one direction.
  • var profit = input.int(-1, title="盈利价差") / syminfo.mintick: Set a parameter that controls how profitable each grid point's holdings are at the price differential to equalize.

Next, look at the code:

if spacing == -1 and amount == -1 and numbers == -1 and profit == -1
    runtime.error("参数错误")

This means that if any of the parameters spacing, amount, numbers, profit are not set to -1, the policy stops. (No parameters can't be set - haha!)

Go on !

if not barstate.ishistory and beginPrice == 0 
    beginPrice := close 

This means that when the policy is in the real-time K-line phase and the startPrice == 0, the modified value to the startPrice is changed to the current latest price. It can be understood that when the policy is officially running, the initial current price is the initial price of the grid. Because the script has a historical K-line BAR phase, the policy will execute logically in the historical BAR phase, it certainly makes no sense to lay the grid on the historical bar.

What is the historical BAR stage?

A simple example is that at the current moment A, the strategy starts running, and the strategy gets a data set of 100 K-line BARs, which over time will definitely be 100 BARs, becoming 101, 102... N. When it starts running at the moment A, the 101st BAR is the real-time K-line phase, which is the latest real-time data. So from the 1st BAR to the 100th BAR, these are all past historical events, but the strategy also runs over these historical events, so this phase is the historical K-line phase.

barstate.ishistoryThis is a built-in variable in the Pine language, and if the current BAR is the BAR of the historical stage, then the current BAR is the bar of the historical stage.barstate.ishistoryIf true, the BAR is false if it is not a history state. If not barstate.ishistory is true, it is in the real-time K-line phase.

And then we're going to create a function.

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 

The function's function is to find out whether an id exists in all orders that have been placed at the moment, and if it exists, the function findTradeId returns the id of the existing cell (note that this ID is not the order ID of the exchange, it is the name or label of the policy for the order), if it does not exist, it returns the string "notFound".

The next thing you know, you're starting to make a grid:

// 实时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)

The for loop is used to determine the number of rounds, i.e. the ordering of the corresponding number of orders, based on the numerical value of the numbers parameter. The dir parameter is used to set the direction. The findTradeId function is used to find whether the order labeled in the current grid position has already been placed, and only to go down the order list when it has not been opened. The bottom order uses the strategy.order function to specify the limit parameter as the order list.

img

img

img

img

Looking at the yield curve, you can see that the grid is also risky, not a win-win, just a little bit less risky on a large scale.

So, if you haven't written a strategy yet with this easy to learn language, Pine, then I'll...


Related

More

StalkerThis type of tutorials can be more than a few, preferably dedicated to pine tutorials ((knowledge paid)hhh 、 dream total v587

artronThank you.

bbbwwed2009The dream total V5

The Little DreamYes, a series of Pine tutorials has been done at Station B: https://www.bilibili.com/video/BV1sU4y1B71i/

The Little DreamThank you for supporting FMZ.

The Little DreamYou can also watch an introductory video on the PINE language on the B station.