Quantified transaction in the coin circle is a new look -- brings you closer to quantified coin circles.

Author: The Little Dream, Created: 2021-05-28 09:50:12, Updated: 2023-09-21 21:06:08

img

Coin circle quantization transaction new look and feel that brings you closer to the coin circle quantization ((5))

In the previous article we discussed the transactional logic analysis of a simple grid strategy, and in this article we continue to complete the design of this teaching strategy.

  • Logical analysis of the trade In the previous article we said that as long as you go through the grid each grid line, judging the current price through the grid line can trigger the trading action. But in reality there are still many logical details, often not understanding the strategy of writing newcomers are easy to form a misconception is that the logic of writing is very simple, the code should be in a few lines, actually writing to find out details or a lot.

    The first thing we want to consider is the design of this aspect of the infinite grid. Remember in the last post we designed a function together that generates the initial grid data structure.createNetSo? This function is generating a grid data structure with a finite number of grid lines. So what if the price goes beyond the boundary of this grid data structure (over the topmost grid line, the highest price, the bottommost grid line, the lowest price) when the strategy is run? So first we need to add an extension mechanism to the grid data structure.

    Start writing the policy main function, which is the code that the policy starts executing.

    var diff = 50                                 // 全局变量,网格间距,可以设计成参数,方便讲解,我们把这个参数写死在代码里。
    function main() {
        // 实盘开始运行后,从这里开始执行策略代码
        var ticker = _C(exchange.GetTicker)       // 获取市场最新的行情数据ticker,ticker这个数据的结构参看FMZ API文档:https://www.fmz.com/api#ticker
        var net = createNet(ticker.Last, diff)    // 我们上篇设计的初始构造网格数据结构的函数,这里构造一个网格数据结构net
    
        while (true) {                            // 然后程序逻辑就进入了这个while死循环,策略执行到此将不停的循环执行这里{}符号之内的代码
            ticker = _C(exchange.GetTicker)       // 死循环代码部分的第一行,获取最新的行情数据,更新给ticker变量
            // 检查网格范围
            while (ticker.Last >= net[net.length - 1].price) {
                net.push({
                    buy : false,
                    sell : false,
                    price : net[net.length - 1].price + diff,
                })
            }
            while (ticker.Last <= net[0].price) {
                var price = net[0].price - diff
                if (price <= 0) {
                    break
                }
                net.unshift({
                    buy : false,
                    sell : false,
                    price : price,
                })
            }
            
            // 还有其它代码...
        }
    }
    

    The grid data structure can be extended with this piece of code (selected from the code above):

          // 检查网格范围
          while (ticker.Last >= net[net.length - 1].price) {   // 如果价格超过网格最高价格的网格线
              net.push({                                       // 就在网格最高价格的网格线之后加入一个新的网格线
                  buy : false,                                 // 初始化卖出标记
                  sell : false,                                // 初始化买入标记
                  price : net[net.length - 1].price + diff,    // 在之前最高价格的基础上再加一个网格间距
              })
          }
          while (ticker.Last <= net[0].price) {                // 如果价格低于网格最低价格的网格线
              var price = net[0].price - diff                  // 区别于向上添加,要注意向下添加新网格线的价格不能小于等于0,所以这里要判断
              if (price <= 0) {                                // 小于等于0就不添加了,跳出这层循环
                  break
              }
              net.unshift({                                    // 就在网格最低价格的网格线之前添加一个新的网格线
                  buy : false,
                  sell : false,
                  price : price,
              })
          }
    

    The next step is to consider how to specifically implement transaction triggering.

    var diff = 50
    var amount = 0.002       // 增加一个全局变量,也可以设计成参数,当然为了简便讲解,我们也写死在策略代码,
                             // 这个参数控制每次网格线上触发交易时的交易量
    function main() {
        var ticker = _C(exchange.GetTicker)
        var net = createNet(ticker.Last, diff)
        var preTicker = ticker       // 在主循环(死循环)开始前,设置一个变量,记录上一次的行情数据
        while (true) {
            ticker = _C(exchange.GetTicker)
            // 检查网格范围
            while (ticker.Last >= net[net.length - 1].price) {
                net.push({
                    buy : false,
                    sell : false,
                    price : net[net.length - 1].price + diff,
                })
            }
            while (ticker.Last <= net[0].price) {
                var price = net[0].price - diff
                if (price <= 0) {
                    break
                }
                net.unshift({
                    buy : false,
                    sell : false,
                    price : price,
                })
            }  
    
            // 检索网格
            for (var i = 0 ; i < net.length ; i++) {     // 遍历网格数据结构中的所有网格线
                var p = net[i]
                if (preTicker.Last < p.price && ticker.Last > p.price) {         // 上穿,卖出,当前节点已经交易过不论SELL BUY ,都不再交易
                    if (i != 0) {
                        var downP = net[i - 1]
                        if (downP.buy) {
                            exchange.Sell(-1, amount, ticker)
                            downP.buy = false 
                            p.sell = false 
                            continue
                        }
                    }
                    if (!p.sell && !p.buy) {
                        exchange.Sell(-1, amount, ticker)
                        p.sell = true
                    }
                } else if (preTicker.Last > p.price && ticker.Last < p.price) {  // 下穿,买入
                    if (i != net.length - 1) {
                        var upP = net[i + 1]
                        if (upP.sell) {
                            exchange.Buy(-1, amount * ticker.Last, ticker)
                            upP.sell = false 
                            p.buy = false 
                            continue
                        }
                    }
                    if (!p.buy && !p.sell) {
                        exchange.Buy(-1, amount * ticker.Last, ticker)
                        p.buy = true 
                    } 
                }
            }
            preTicker = ticker    // 把当前的行情数据记录在preTicker中,在下一次循环中,作为“上一次”行情数据和最新的对比,判断上穿下穿
            Sleep(500)
        }
    }  
    

    You can see:

    • Conditions for crossing the grid:preTicker.Last < p.price && ticker.Last > p.price
    • The following are the conditions for entering the grid:preTicker.Last > p.price && ticker.Last < p.price

    I'm not sure what you're talking about.

    img

    Going up and down is only the first step in deciding whether to place a transaction, which also includes deciding on the markings in the grid data.

    If the price is lower than the current grid line and the buy mark on the most recent grid line, if the value of the buy mark is true, the buy mark on the last grid line is reset to false, and the sell mark on the current grid line is reset to false.

    After judging the conditions just stated, if there is no trigger, then continue judging, if the current grid line buy/sell markings are all false, then the current grid line can be traded, since it is overlaid, we here perform sell operation, after executing mark the current grid line sell mark true.

    The same logic applies here (let's leave it to the newcomers to think).

The full strategy review

So to see some of the data when we retested, we wrote a function.showTblDisplaying data.

function showTbl(arr) {
    var tbl = {
        type : "table", 
        title : "网格",
        cols : ["网格信息"],
        rows : []
    }
    var arrReverse = arr.slice(0).reverse()
    _.each(arrReverse, function(ele) {
        var color = ""
        if (ele.buy) {
            color = "#FF0000"
        } else if (ele.sell) {
            color = "#00FF00"
        }
        tbl.rows.push([JSON.stringify(ele) + color])
    })
    LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`", "\n 账户信息:", exchange.GetAccount())
}

The full strategy code:

/*backtest
start: 2021-04-01 22:00:00
end: 2021-05-22 00:00:00
period: 1d
basePeriod: 1m
exchanges: [{"eid":"OKEX","currency":"ETH_USDT","balance":100000}]
*/

var diff = 50
var amount = 0.002
function createNet(begin, diff) {
    var oneSideNums = 10
    var up = []
    var down = []
    for (var i = 0 ; i < oneSideNums ; i++) {
        var upObj = {
            buy : false,
            sell : false, 
            price : begin + diff / 2 + i * diff,
        }
        up.push(upObj)

        var j = (oneSideNums - 1) - i
        var downObj = {
            buy : false,
            sell : false,
            price : begin - diff / 2 - j * diff,
        }
        if (downObj.price <= 0) {  // 价格不能小于等于0 
            continue
        }
        down.push(downObj)
    }

    return down.concat(up)
}

function showTbl(arr) {
    var tbl = {
        type : "table", 
        title : "网格",
        cols : ["网格信息"],
        rows : []
    }
    var arrReverse = arr.slice(0).reverse()
    _.each(arrReverse, function(ele) {
        var color = ""
        if (ele.buy) {
            color = "#FF0000"
        } else if (ele.sell) {
            color = "#00FF00"
        }
        tbl.rows.push([JSON.stringify(ele) + color])
    })
    LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`", "\n 账户信息:", exchange.GetAccount())
}

function main() {
    var ticker = _C(exchange.GetTicker)
    var net = createNet(ticker.Last, diff)
    var preTicker = ticker 
    while (true) {
        ticker = _C(exchange.GetTicker)
        // 检查网格范围
        while (ticker.Last >= net[net.length - 1].price) {
            net.push({
                buy : false,
                sell : false,
                price : net[net.length - 1].price + diff,
            })
        }
        while (ticker.Last <= net[0].price) {
            var price = net[0].price - diff
            if (price <= 0) {
                break
            }
            net.unshift({
                buy : false,
                sell : false,
                price : price,
            })
        }

        // 检索网格
        for (var i = 0 ; i < net.length ; i++) {
            var p = net[i]
            if (preTicker.Last < p.price && ticker.Last > p.price) {         // 上穿,卖出,当前节点已经交易过不论SELL BUY ,都不再交易
                if (i != 0) {
                    var downP = net[i - 1]
                    if (downP.buy) {
                        exchange.Sell(-1, amount, ticker)
                        downP.buy = false 
                        p.sell = false 
                        continue
                    }
                }
                if (!p.sell && !p.buy) {
                    exchange.Sell(-1, amount, ticker)
                    p.sell = true
                }
            } else if (preTicker.Last > p.price && ticker.Last < p.price) {  // 下穿,买入
                if (i != net.length - 1) {
                    var upP = net[i + 1]
                    if (upP.sell) {
                        exchange.Buy(-1, amount * ticker.Last, ticker)
                        upP.sell = false 
                        p.buy = false 
                        continue
                    }
                }
                if (!p.buy && !p.sell) {
                    exchange.Buy(-1, amount * ticker.Last, ticker)
                    p.buy = true 
                } 
            }
        }

        showTbl(net)
        preTicker = ticker 
        Sleep(500)
    }
}

This is the first time I've seen this video.

img

img

img

As you can see, the characteristics of the grid strategy are that there will be a large surge in losses when there is a trend in the market, and the earnings will recover only after the market is shaken. So the grid strategy is not risk-free, the spot strategy can still lie on the sidelines, while the futures contract grid strategy is more risky, requiring conservative settings for the grid parameters.


Related

More

husr12345This is C++.

tony233I think there's a logical flaw here, shouldn't it be that when you go to sell, you have to go through a grid line that is higher than the current price? There's also exchange.Sell ((-1, amount, ticker) How is this function different from the one in the API documentation, I see that the API documentation says exchange.Sell ((Price, Amount), why do you have three parameters, I don't understand, it's very complicated, I'm also crazy

tony233It's not easy.

hawlWhen the price of the stock is going up and down, exchange.Buy ((-1, amount * ticker.Last, ticker), amount * ticker.Last is a joke, why not sell?

CYZWX https://www.fmz.com/strategy/291160 last_tick = [] line = [] grid_buy_list = [] def net(now_price): global line print(now_price) line = [now_price*(1+0.003*i) for i in range(-1000,1000)] Log(line) def ontick(): global last_tick global line global grid_buy_list account = exchange.GetAccount() ticker = exchange.GetTicker() last_tick.append(ticker['Last']) if len(last_tick) == 1:return elif len(last_tick) == 100:del last_tick[0] for i in range(len(line)): if last_tick[-1] > line[i] and last_tick[-2] < line[i] and len(grid_buy_list)!= 0 and i > min(grid_buy_list) and account['Stocks'] >= 0.001: exchange.Sell(last_tick[-1],0.01) del grid_buy_list[grid_buy_list.index(min(grid_buy_list))] Log(exchange.GetAccount()) elif last_tick[-1] < line[i] and last_tick[-2] > line[i] and i not in grid_buy_list: exchange.Buy(last_tick[-1],0.01) grid_buy_list.append(i) Log(exchange.GetAccount()) def main(): net(exchange.GetTicker()['Last']) Log(exchange.GetAccount()) while(True): ontick() Sleep(1000)

CYZWXThanks to Dream God, it's very detailed, I'll buy it again and explain it, it's like writing a py version.

The Little DreamThe strategy is the JavaScript language.

tony233Is a permanent contract not a futures contract?

The Little DreamFutures are the number of contracts, and spot market prices are the amount of the order; spot orders are the number of coins.

tony233Dear Sir, I would like to ask you another question, this is a joke. Note: the exchange's order sub-interface supports market price lists (the order type is the payment, the order parameter is the amount of currency unit) ‒ the digital currency futures market order method, the order parameter is the number of contracts. I see that this post is a test of the USDT perpetual contract of OKEX, which does not count the order method for the market price list.

tony233Oh, I see.

The Little DreamFMZ's API functions can generate log output functions such as: Log ((...), exchange.Buy ((Price, Amount), exchange.CancelOrder ((Id) etc. with some additional output parameters after the necessary parameters.