前回の記事では,簡単な格子戦略の取引論理分析について説明しましたが,この記事では,この学習戦略の設計を完成させています.
取引論理分析 前回の記事では,ネットの各グリッドラインを横切って,現在の価格を判断し,グリッドラインを通過すると取引動作を誘発すると述べた. しかし,実際には論理の詳細はたくさんあります. 戦略を書き込むことを理解しない新人達は,しばしば誤った認識を形成することが容易です.
まず最初に考えたいのは,無限格子の設計です. 前回の記事で,最初の格子データ構造を生成する関数を設計しました.createNet
この関数は,グリッドラインが有限数のグリッドデータ構造を生成します. 戦略を実行するときに,価格がグリッドデータ構造の境界を超えた場合 (上位は最高価格,下位は最低価格) はどうでしょうか?
格子データ構造に拡張メカニズムを加える必要があります.
実行を開始するコードです. 実行を開始するコードです. 実行を開始するコードです.
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,
})
}
// 还有其它代码...
}
}
格子データ構造を拡張するには,このコード (上記のコードから選択):
// 检查网格范围
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,
})
}
取引のトリガーを実現するための具体的な方法について考えます.
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)
}
}
メディアは,
preTicker.Last < p.price && ticker.Last > p.price
preTicker.Last > p.price && ticker.Last < p.price
この記事へのトラックバック一覧です.
上下を切り替えるのは,取引を許可するか否かを判断する最初のステップに過ぎず,グリッドラインのデータに記入されているマークも判断する必要があります.
格子上では,現在の格子線と最近の格子線上のbuyマークを下回る価格を判断し,buyマークの値がtrueである場合,前の格子線が購入されたことを示します.上にあるbuyマークをfalseに,現在の格子線をsellマークにfalseに再設定します.
先ほどの条件を判断した後に,もし触発がない場合,判断を続けます.もし現在の格子線上のbuy/sellマークがすべてfalseであるならば,現在の格子線が取引可能であることを示します.上着であるため,ここで販売操作を実行し,実行後に現在の格子線をマークします. sellマークはtrueです.
フォローしているブログでは,この記事へのトラックバック一覧です.
復習したデータを見ることができるように,関数を書きましょう.showTbl
データを表示します.
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())
}
策略のコードはこちら
/*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)
}
}
策略を振り返る:
格子戦略の特徴は,トレンドのある市場に出くわしたとき,大きな浮出損失があり,波動した市場の下での収益が回復する. したがって,格子戦略はリスクのないものではない. 現金戦略は平凡な硬いままに眠りにつくことができるが,フューチャー契約格子戦略はリスクが大きいので,格子パラメータに対して保守的な設定が必要である.
ハスル12345これはC++です.
トニー233格子線が3つのパラメータを持っているのに,理解できない,複雑だ,私もおかしくなった. 格子線が3つのパラメータを持っているのに,私は3つのパラメータを持っている. 格子線が3つのパラメータを持っているのに,私は3つのパラメータを持っている. 格子線が3つのパラメータを持っているのに,私は3つのパラメータを持っている.
トニー233難しかった
ハール上り下りすると,exchange.Buy ((-1, amount * ticker.Last, ticker),amount* ticker.Lastは,
CYZWXhttps://www.fmz.com/strategy/291160 last_tick = [] チェックする 線 = [] grid_buy_list = [] このリストは def 純 ((now_price) について) グローバルライン print ((now_price) 価格について ライン = [now_price*(1+0.003*i) for i in range ((-1000,1000) ] ログ (ライン) わかった デフオンティック (: グローバル最後のチェック グローバルライン グローバルグリッド_購入_リスト アカウント = 交換.GetAccount (() ticker = exchange.GetTicker (ティッカー=交換する) last_tick.append ((ticker['ラスト']) と表示する if len ((last_tick) == 1:返信する エリフ・レン (最後のチェック) == 100:del last_tick[0] i の範囲 ((len)) のライン): if last_tick[-1] > line[i] and last_tick[-2] < line[i] and len(grid_buy_list)!= 0 と i > min(grid_buy_list) とアカウント['ストック'] >= 0.001: 交換.売る ((最後の_ティック[-1],0.01) 格子_購入_リスト[格子_購入_リスト.インデックス ((min(格子_購入_リスト))] ログ (※) 交換 (※) アカウント (※) elif last_tick[-1] < line[i] と last_tick[-2] > line[i] と i が grid_buy_list にない場合: 交換.購入 (最後のチェック[-1],0.01) grid_buy_list.append ((i) について ログ (※) 交換 (※) アカウント (※) 定義 メイン (: (ネット (交換) ゲット (Ticker) [最後の] ログ (※) 交換 (※) アカウント (※) 本当です チェック (tick)) 睡眠 (1000)
CYZWX詳細を述べてくれてありがとう. また買おうとすると説明します. まるでpy版のように.
発明者 量化 - 微かな夢戦略はJavaScriptの言語である.
トニー233長期契約は先物として扱われないのか?
発明者 量化 - 微かな夢フューチャーとは契約書の数であり,現金市場価格で支払いは金額である.現金販売はコインの数である.
トニー233大
トニー233わかったわ
発明者 量化 - 微かな夢FMZのAPI関数では,Log (※)...,exchange (※) ・Buy (※) ・Price (※) ・Amount (※) ・exchange (※) ・CancelOrder (※) ・Id (※) などなどのログ出力関数を生成することができる.必要パラメータの後には,付属した出力パラメータも含まれます.https://www.fmz.com/api#exchange.cancelorderid