Perdagangan kuantitatif dalam lingkaran mata wang adalah sesuatu yang baru -- membawa anda lebih dekat kepada kuantitatif dalam lingkaran mata wang.

Penulis:Mimpi kecil, Dicipta: 2021-05-28 09:50:12, Dikemas kini: 2023-09-21 21:06:08

img

Perdagangan kuantitatif lingkaran wang yang baru muncul membawa anda lebih dekat dengan kuantitatif lingkaran wang.

Dalam artikel sebelumnya, kami telah menerangkan analisis logik transaksi strategi grid yang mudah, dan dalam artikel ini, kami akan meneruskan untuk menyempurnakan reka bentuk strategi ini.

  • Analisis Logik Perdagangan Dalam artikel sebelumnya, kita mengatakan bahawa hanya melalui setiap garisan grid, menilai harga semasa melalui garisan grid dan boleh mencetuskan tindakan dagangan. Tetapi sebenarnya terdapat banyak butiran logik, yang seringkali tidak memahami strategi yang ditulis oleh pemula yang mudah terbentuk satu persepsi yang salah adalah logik yang sangat mudah, kod harus hanya dalam beberapa baris, tetapi sebenarnya ditulis untuk mencari butiran atau banyak.

    Pertama, butiran pertama yang perlu kita pertimbangkan ialah reka bentuk grid tanpa had.createNetJadi? Fungsi ini menghasilkan struktur data grid yang mempunyai bilangan grid yang terhad. Jadi, jika harga melebihi sempadan struktur data grid ini semasa menjalankan strategi (di atas adalah harga tertinggi, di bawah adalah harga terendah) Oleh itu, pertama-tama kita perlu menambah mekanisme pelanjutan kepada struktur data grid.

    Mulakan menulis fungsi utama, yang merupakan kod untuk memulakan pelaksanaan.

    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,
                })
            }
            
            // 还有其它代码...
        }
    }
    

    Untuk memperluaskan struktur data grid adalah dengan kod ini (dipetik dari kod di atas):

          // 检查网格范围
          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,
              })
          }
    

    Pada peringkat seterusnya, kita perlu mempertimbangkan bagaimana untuk mencapai pemicu transaksi secara konkrit.

    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)
        }
    }  
    

    Di sini anda boleh melihat:

    • Syarat untuk menaiki grid:preTicker.Last < p.price && ticker.Last > p.price
    • Di bawah ini adalah syarat untuk memasuki grid:preTicker.Last > p.price && ticker.Last < p.price

    Ini adalah apa yang kita katakan dalam artikel sebelumnya:

    img

    Menerusi melalui hanya langkah pertama untuk menentukan sama ada pesanan boleh dibuat, termasuk menentukan tanda-tanda dalam data grid.

    Jika naik, maka harga dinilai lebih rendah daripada garisan semasa dan tanda beli pada garisan terkini. Jika nilai tanda beli adalah benar, maka menunjukkan bahawa garisan sebelumnya telah dibeli, maka tanda beli yang berada di atas akan diletakkan semula sebagai palsu, dan tanda jual pada garisan semasa akan diletakkan semula sebagai palsu.

    Setelah menilai keadaan yang baru sahaja berlaku, jika tidak ada pencetus, teruskan menilai, jika tanda beli / jual pada garisan grid semasa adalah salah, maka ini menunjukkan bahawa garisan grid semasa boleh diperdagangkan, kerana ia memakai, kita di sini melaksanakan operasi jual, selepas menjalankan tanda sell pada garisan grid semasa tanda benar.

    Di sini, kita akan melihat bagaimana orang yang baru belajar akan berfikir.

Ujian semula strategi penuh

Untuk melihat beberapa data semasa pengukuran semula, saya menulis fungsi.showTblTunjukkan 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())
}

Kode strategi penuh:

/*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)
    }
}

Rujukan strategi:

img

img

img

Seperti yang dapat dilihat dari ciri-ciri strategi grid, apabila terdapat pasaran yang sedang trend, akan ada kerugian yang lebih besar, dan pendapatan akan pulih selepas pasaran yang bergolak. Oleh itu, strategi grid tidak bebas daripada risiko, strategi semasa masih boleh berbaring dengan keras, tetapi strategi grid kontrak niaga hadapan lebih berisiko dan memerlukan tetapan yang terlalu konservatif untuk parameter grid.


Berkaitan

Lebih lanjut

husr12345Ini adalah bahasa C++.

Tony233Saya rasa ada kelemahan logik di sini, bukankah anda harus pergi melalui garis grid yang lebih tinggi daripada harga semasa ketika anda memakainya? Ada juga exchange.Sell ((-1, jumlah, ticker) bagaimana fungsi ini berbeza dengan dokumen api, saya melihat dokumen api menulis exchange.Sell ((Price, Amount), mengapa anda mempunyai tiga parameter, saya tidak faham, agak rumit, saya juga gila

Tony233Sukar.

HawlApabila naik dan turun, exchange.Buy ((-1, amount * ticker.Last, ticker), amount * ticker.Last adalah hal yang tidak masuk akal, mengapa tidak ada penjual?

CYZWXhttps://www.fmz.com/strategy/291160 last_tick = [] baris = [] grid_buy_list = [] def net ((now_price): Garis global print ((now_price) baris = [now_price*(1+0.003*i) untuk i dalam julat ((-1000,1000) ] Log (garis) def ontick ((): global last_tick Garis global global grid_buy_list akaun = pertukaran.GetAccount() ticker = pertukaran.GetTicker() last_tick.append ((ticker['Last']) jika len ((last_tick) == 1:kembali elif len ((last_tick) == 100:del last_tick[0] untuk i dalam julat ((len)) garis): jika last_tick[-1] > baris[i] dan last_tick[-2] < baris[i] dan len ((grid_buy_list)!= 0 dan i > min ((grid_buy_list) dan akaun['Stock'] >= 0,001: pertukaran.Menjual ((last_tick[-1],0.01) del grid_buy_list[grid_buy_list.index(min(grid_buy_list))] Log ((exchange.GetAccount()) elif last_tick[-1] < baris[i] dan last_tick[-2] > baris[i] dan i tidak dalam grid_buy_list: pertukaran.Buy ((last_tick[-1],0.01) grid_buy_list.append (i) Log ((exchange.GetAccount()) def utama ((): net ((exchange.GetTicker() ['Terakhir']) Log ((exchange.GetAccount()) sementara(Benar): pada tetikus() Tidur ((1000)

CYZWXTerima kasih kepada Dream God, ia sangat terperinci, saya akan membeli semula dan menerangkan semuanya, seolah-olah saya telah menulis versi py.

Mimpi kecilStrategi ini adalah bahasa Javascript.

Tony233Adakah kontrak kekal dalam teks tidak dianggap sebagai masa hadapan?

Mimpi kecilMasa hadapan adalah jumlah kontrak, harga pasaran semasa adalah jumlah pesanan; pesanan jualan segera adalah jumlah mata wang.

Tony233Saya ingin bertanya satu lagi soalan, ini adalah satu teka-teki. Perhatikan: memerlukan pertukaran yang menggunakan antara muka pesanan bawah untuk menyokong senarai harga pasaran ((jenis pesanan untuk pembayaran, parameter jumlah pesanan bawah adalah jumlah mata wang dalam satu unit) ‒ pesanan harga pasaran mata wang hadapan digital, unit parameter jumlah pesanan adalah jumlah kontrak. Saya melihat bahawa anda menulis kembali kontrak kekal USDT untuk etokex, yang tidak mengira kaedah pesanan bagi pesanan pasaran hadapan?

Tony233Oh, saya faham.

Mimpi kecilFungsi API FMZ boleh menghasilkan fungsi output log seperti: Log ((...) ; exchange.Buy ((Price, Amount) ; exchange.CancelOrder ((Id) dan lain-lain dengan beberapa parameter output tambahan selepas parameter yang diperlukan.