ネットワーク取引戦略 (www.fmz.com) 格子取引の基本考え方は非常に単純です. 1つの取引を行う代わりに,複数の取引を格子パターンを形成して行う.通常は,現在の価格レベル周辺の"ストップ"または"制限"オーダーとして入力されますが,必ずしもそうではありません.以下に詳細に説明しますが,基本アイデアはこれです.
グリッド・トレーディングとは何か? どのように機能するのか? 格子取引は市場変動を操作するものです.トレーダーが好む理由は2つあります.第一に,市場の方向性について明確な予測が必要ないということです.
2つ目は 変動が激しい市場ではうまく機能し 明確な傾向がないことです
グリッド取引は,特定のグリッドパターン内の動きに基づいた技術分析取引の一種である. グリッド取引は外為取引で人気がある. 全体的に,この技術は,既定のベース価格の上下で一定の定期的な間隔で購入・販売オーダーを置き,市場の通常の価格変動から利益を得ることを目指している.そのような購入・販売オーダーは,一般的に10〜15ユニットの間隔で隔離され,取引グリッドを作成する.
グリッドは方向をカスタマイズできます
基本的な取引:まず買い,それから売る.
グリッドは,最初の価格を下回る価格で購入注文を送信し始めます.これは最初の価格が続く価格です (第2の最新の購入価格,第3の最新の購入価格...など).各購入注文は"価格間隔"パラメータで区切られています.待機中の注文の数は"単一の量"で,"総量"が満たされるまで注文総数を送信します.
購入オーダーが完了した後,プログラムは購入価格に基づいて,注文が販売された後,販売価格に価格の"価格差"パラメータを追加し,その後,このグリッド戦略の進行を再開します (チェック,注文を配置,実行されるまで待って,販売)
まずショートセール,その後カバーで購入: 操作は正反対です
この戦略の最大のリスクは 市場の動向が一方的で 価格変動が格子を超えている場合です
次のコードは,自動ストップ損失と動きの機能を持つグリッドを作りました.
コメント:
この戦略は,仮想待機注文デザインを使用し,待機注文数を制限するために取引所に多くの処理を提供し,問題を柔軟に解決します.
格子論理は柔軟な設計で 巧みな構造です
利益と損失の計算,各数値統計アルゴリズムは参照として使用することができ,各条件検出設計は厳格です. (BUGの可能性を最小限に抑えるため)
ソースコードは学ぶ価値がある.
詳細については,以下を参照してください.
https://www.fmz.com/strategy/112633
ソースコード:
// ソースコード: /* インターフェースパラメータ (コードでグローバル変数として表示) OpTypeグリッド方向 ドロップダウンボックス (選択) 最初に購入して販売します. FirstPriceAuto 初期価格 自動ブーリアン (真/偽) true ファーストプライス@!ファーストプライス 自動初期価格 数字 (番号) 100 全数 総数 数字数 (数) 10 価格グリッド 価格区間 数字 (数) 1 価格差値差 (数) 2 同じ金額を購入して販売します カスタム金額 SummOnce@AmountType==0 単一のトランザクションの数値 (数) 0.1 BAmountOnce@AmountType==1 購入注文 番号のサイズ (数) 0.1 SAmountOnce@AmountType==1 販売注文のサイズ 番号 0.1 AmountCoefficient@AmountType==0 量差 文字列 (文字列) *1 SummDot 数字の小数点 (数) 3 EnableProtectDiff スプレッド保護をオンにする ブール式 (true/false) false ProtectDiff@EnableProtectDiff エントリー・スプレッド 価格保護 数字 (番号) 20 CancelAllWSストップ 待機中の注文をすべてキャンセル ブール式 (真/偽) true CheckInterval 投票間隔番号 数字 (番号) 2000 インターバル失敗 復試間隔 数値 (数) 1300 RestoreProfit 最後の利益を復元します ブール式 (真/偽) false LastProfit@RestoreProfit ラスト・プロフィット 数字 (数) 0 ProfitAsOrg@RestoreProfit 平均価格としてカウントされた最後の利益 ブール式 (真/偽) false EnableAccountCheck バランス検証を有効にする ブーリアン (true/false) true EnableStopLoss@EnableAccountCheck オープン ストップ ロス ブーリアン (true/false) false StopLoss@EnableStopLoss 最大変動損失数 (数) 100 StopLossMode@EnableStopLoss 停止後損失操作 ドロップダウンボックス (選択済み) リサイクル&出口 EnableStopWin@EnableAccountCheck 利益を取ることをオンにします ブーリアン (真/偽) false StopWin@EnableStopWin 最大変動利益 番号タイプ (番号) 120 StopWinMode@EnableStopWin 利益を取った後の操作のドロップダウンボックス (選択) リサイクル&退出 AutoMove@EnableAccount チェック オート 移動 ブール式 (true/false) false MaxDistance@AutoMove 最大数値距離 (数) 20 MaxIdle@AutoMove 最大無作動 (秒) 数値 (数) 7200 EnableDynamic ダイナミック待機注文を回転する ブール式 (true/false) false DynamicMax@EnableDynamicオーダーの有効期限距離 番号 (番号) 30 ResetData は起動時にすべてのデータを削除します ブーリアン (真/偽) true 精度価格 十進数値 (数) 5 */
function hasOrder ((orders, orderId) { // パラメータのオーダーでオーダーIDを持つオーダーがあるかどうかをチェックする for (var i = 0; i < orders.length; i++) { // 同じ id が存在するかどうかをチェックするために命令を横断します. if (order[i].Id == orderId) { true を返す. { \ pos (192,220) } { \ pos (192,220) } 返信 false; // すべての横断,トリガーがない場合,ID orderId の順序が見つからない場合,返信 false { \ pos (192,220) }
function cancelPending() { // 待機中のすべての注文関数をキャンセルする var ret = false; // 変数を返信成功タグに設定する while (true) { // whileループを表示する if (ret) { // if ret is true then Sleep for a certain time もし (ret) { // もし (ret) が本当なら ある時間眠る 睡眠 (インターバル) { \ pos (192,220) } 交換が実行しなかった注文情報を API に呼び出す. if (orders.length == 0) { // 空の配列が返される場合,交換には実行されていない命令がありません. break; // whileループからジャンプ { \ pos (192,220) }
for (var j = 0; j < orders.length; j++) { // Traverse the unfinished order array and use orders[j].Id one by one to cancel the order based on the index j.
exchange.CancelOrder(orders[j].Id, orders[j]);
ret = true; // Once there is a cancel operation, ret is assigned a value of true. Used to trigger above Sleep, wait for re-exchange.GetOrders detection
}
}
return ret; // return ret
}
function valuesToString(values, pos) { // 文字列に変換された値
var result =
トレーダーの関数,閉じる.
var vId = 0; // 注文インクリメント ID
var orderBooks = []; // 注文簿
var hisBooks = []; // 歴史的な順序帳
var orderBooksLen = 0; // 注文簿の長さ
this.Buy = function ((価格,金額,追加) { // 購入機能,パラメータ:価格,量,拡張情報
if (typeof(extra) ===
if (orders[i].Id == order.Id) { // orderBooksで同じorder idを持つorderを見つけると,trueの値を findに代入します.これは findという意味です.
発見 = true;
break; // 現在のループからジャンプ
{ \ pos (192,220) }
{ \ pos (192,220) }
if (!found) { // 見つからない場合は,orderBooks[orderId] を命令に押します.
orders.push ((orderBooks[orderId]); // なぜこんな風に押したいのか?
{ \ pos (192,220) }
{ \ pos (192,220) }
返品命令; //返品命令
{ \ pos (192,220) }
this.GetOrder = function ((orderId) { // 命令を取得する
if (typeof(orderId) ===
var pfn = order.Type == ORDER_TYPE_BUY ? exchange.Buy : exchange.Sell; // Assign the corresponding API function reference to pfn according to the type of the order.
// That is, if the order type is a buy order, pfn is a reference to the exchange.Buy function, the same as the sell order.
if (order.Id == 0 && diff <= priceDiff) { // If the order order in the order book is not activated (ie Id is equal to 0) and the current price is less than or
// equal to the order plan price, the priceDiff passed in the parameter.
var realId = pfn(order.Price, order.Amount, order.Extra + "(distance: " + diff + (order.Type == ORDER_TYPE_BUY ? (" ask price: " + ticker.Buy) : (" bid price: " + ticker.Sell))+")");
// Execute order function, parameter passing price, quantity, order extension information + pending order distance + market data (ask price or bid price), return exchange order id
if (typeof(realId) === 'number') { // If the returned realId is a numeric type
order.Id = realId; // Assign the Id attribute of the current order order to the order book.
}
} else if (order.Id > 0 && diff > (priceDiff + 1)) { // If the order is active and the current distance is greater than the distance passed in by the parameter
var ok = true; // Declare a variable for tagging Initially set true
do { // Execute "do" first and then judge while
ok = true; // Ok assign true
exchange.CancelOrder(order.Id, "unnecessary" + (order.Type == ORDER_TYPE_BUY ? "buying" : "selling"), "placed order price:", order.Price, "volume:", order.Amount, ", distance:",
diff, order.Type == ORDER_TYPE_BUY ? ("ask price: " + ticker.Buy) : ("bid price: " + ticker.Sell));
// Cancel the pending order that is out of range. After canceling the order, print the current order information and the current distance diff.
Sleep(200); // Wait 200 milliseconds
orders = _C(exchange.GetOrders); // Call the API to get an uncompleted order in the exchange.
for (var i = 0; i < orders.length; i++) { // Traverse these unfinished orders.
if (orders[i].Id == order.Id) { // If the cancelled order is found in the list of orders that have not been completed by the exchange
ok = false; // Assign ok this variable to false, that is, no cancellation is successful.
}
}
} while (!ok); // If ok is false, then !ok is true and while will continue to repeat the loop, continue to cancel the order,
// and check if the cancellation is successful.
order.Id = 0; // Assigning a value of 0 to order.Id means that the current order is inactive.
}
}
};
}
function balanceAccount ((orgAccount, initAccount) { // Balance Account Function Parameter 戦略が開始されたときに最初のアカウント情報
cancelPending (((); //Call the custom function cancelPending ((() to cancel all pending orders (すべての未定の注文をキャンセルするためにカスタム関数を呼び出す)
var nowAccount = _C ((exchange.GetAccount); // この時点でアカウントに関する最新の情報を記録するために, nowAccount を変数として宣言します.
< slidePrice = 0.2; // Order を 0.2 として置くとき,スリップ価格を設定する
< start="2150.567" dur="0.067"> < start="2150.567" dur="0.067"> < start="2150.567" dur="0.067"> < start="2308.568" dur="0.067"> < start="2308.573"> < start="2308.573" dur="0.067"> < start="2308.573"> < start="2309.573"> < start="2309.573" dur="0.067"> < start="2309.573"> < start="2309.568"> < start="2309.568" dur="0.067"> < start="2309.568"> < start="2309.568" dur="0.067"> < start="2309.567" dur="0.067"> >
ループを起動する
var diff = _N ((nowAccount.Stocks - initAccount.Stocks); // 計算する現在の口座と初期口座の差
if (Math.abs(diff) < exchange.GetMinStock()) { // If the absolute value of the currency difference is less than the minimum transaction volume of the exchange, if (Math.abs(diff) < exchange.GetMinStock()) { // If the absolute value of the currency difference is less than the minimum transaction volume of the exchange, if (Math.abs(diff) < exchange.GetMinStock()) { // If the absolute value of the currency difference is less than the minimum transaction volume of the exchange, if (Math.abs(diff) < exchange.GetMinStock()) { // If the absolute value of the currency difference is less than the minimum transaction volume of the exchange, if (Math.abs(diff) < exchange.
// the break はループから飛び出してバランス操作を行わない.
ブロンクス:
{cH00ffff}
var depth = _C ((exchange.GetDepth); // Get the exchange depth information 宣言された深さ変数に割り当て
var books = diff > 0? depth.Bids : depth.Asks; // According to the difference of the currency is greater than 0 or less than 0, the buy order array or extract the buy order array or
// sell order array in depth (equal to 0 will not be processed, it is break when it is judged to be less than GetMinStock) // オーダーが0に等しい場合は,処理されません.
コインの差は0より大きいので,購入注文の配列を見てください.
// the difference between the coins is less than 0 is the opposite コインの差が0より小さいのは逆です
変数 n = 0; // ステートメント n 初期は 0
< start="2150.539" dur="0.067"> 価格が表示されているように,
for (var i = 0; i < books.length; i++) { // トラバーシング the buy or sell order アレイ
n += books[i].Amount; // Accumulate Amount (order quantity) for each order based on the index i traversed オーダーが1つずつ行われている場合の総量
if (n >= Math.abs(diff)) { // If the cumulative order quantity n is greater than or equal to the currency difference, then: 累積順序量 n は通貨差よりも大きいまたはそれと同等である場合
price = books[i].Price; // Get the price of the current indexed order, assign it to price 価格を表示する 価格を表示する
break; // Jump out of the current for traversal cycle トランバーサルサイクルのための現在のジャンプ
{cH00ffff}
{cH00ffff}
var pfn = diff > 0? exchange.Sell : exchange.Buy; // 売り注文 API (exchange.Sell) または次の買い注文 API (exchange.Buy) の参照を宣言された pfn に渡す
// 0 より大きいまたは 0 より少ない通貨差に基づいて
var amount = Math.abs(diff); // The amount of the order to be balanced is diff, the difference in the currency, assigned to the declared amount variable. / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
var price = diff > 0? (価格 - スライドPrice) : (価格 + スライドPrice); // The direction of buying and selling according to the difference in the currency, increase or decrease the 通貨の違い,通貨の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い,価格の違い
// スリップ価格は価格に基づいて,そしてそれを価格に割り当てます.
Log ((
var STATE_WAIT_OPEN = 0; // fishTable の各ノードの状態のために使用されます var STATE_WAIT_COVER = 1; //... var STATE_WAIT_CLOSE = 2; //... 試行錯誤を表示する var ProfitCount = 0; // 損益記録 var BuyFirst = true; // 初期インターフェースパラメータ var IsSupportGetOrder = true; // 交換サポートを決定 メイン関数の開始を決定するために使用されるグローバル変数である GetOrder API関数 var LastBusy = 0; // 最後に処理された時間オブジェクトを記録する
関数 setBusy() { // 忙しい時間を設定する LastBusy = new Date(); // 現在の時間オブジェクトにLastBusyを割り当て { \ pos (192,220) }
isTimeout (時間切れ) { // 時間切れを決定する if (MaxIdle <= 0) { // 最大無作動時間 (グリッドが自動的に移動されるかどうかに基づいて) // 最大無効時間 MaxIdle が 0 未満または 0 に等しいと設定されている場合 false を返します. // false を返します. タイムアウトを判断しません. つまり,タイムアウトなしで常に false を返します. { \ pos (192,220) } var now = new Date ((); // 現在の時間オブジェクトを取得 if (((now.getTime() - LastBusy.getTime()) / 1000) >= MaxIdle) { // 差を計算するために,タイムスタンプとLastBusyのタイムスタンプを取得するために,現在のタイムオブジェクトのgetTime関数を使用します. // 2つの時間オブジェクト間の秒数を計算するために1000で割ります. // 最大無作業時間 MaxIdle より大きいかどうかを決定する LastBusy = now; // より大きい場合は,現在タイムオブジェクトに更新します. true を返します. // は true を返します. これはタイムアウトです. { \ pos (192,220) } false を返します. // false を返します. { \ pos (192,220) }
プログラム終了時に閉じる関数.
if (CancelAllWS) { // 停止時にすべての待機注文をキャンセルするには,すべての待機注文をキャンセルするために cancelPending() を呼びます.
ログ ((
釣り機能 (org) 釣り数 (数) { // 釣りパラメータ: 釣り情報,釣り数
setBusy(); // 現在のタイムスタンプに LastBuys をセットする
経費情報を取得し,それを割り当てるためにアカウント変数を宣言します.
Log ((アカウント); // 釣り機能への呼び出しの開始時にアカウント情報を出力します.
変数 InitAccount を宣言し,それをアカウントに割り当てます.ここでは,以前に記録された最初のアカウントの資金です.
浮動利益と損失を計算するために使用されます.
var ticker = _C(exchange.GetTicker); // 宣言された ticker 変数に代入値を割り当てます
var amount = _N(AmountOnce); // インターフェースパラメータの数に応じて, _N を使って小数点を処理し (_N は 2 ビットにデフォルトで設定されています) amount に割り当てます.
変数 amountB = [ amount]; // 変数 amountB を array と宣言し,element を amount と初期化します
変数を宣言する.
if (typeof(AmountType)!==
{ \ pos (192,220) }
// 魚のテーブルを初期化
var fishTable = {}; //グリッドオブジェクトを宣言する
var uuidTable = {}; // 識別コードテーブルオブジェクト
var needStocks = 0; // 必要なコイン 変数
var needMoney = 0; // 必要なお金変数
< actualNeedMoney = 0; // 実際にお金が必要でした
actualNeedStocks = 0; //実際に必要なコイン
var notEnough = false; // 資金不足のタグ変数,最初は false に設定されています
var canNum = 0; // 利用可能なグリッド
for (var idx = 0; idx < AllNum; idx++) { // 構造はグリッドの番号 AllNum に基づいて横断されます.
var price = _N((BuyFirst? FirstPrice - (idx * PriceGrid) : ファーストプライス + (idx * PriceGrid)), 精度);
// コンストラクタを横断する際に,現在のインデックス idx 価格設定は BuyFirst に基づいて設定されます.各インデックス価格の間の間隔は PriceGrid です.
needStocks += amountS[idx]; // 販売されたコインの数がサイクルとともに徐々に蓄積されます. (売り注文量配列によって needStocksに1つずつ蓄積されます)
needMoney +=価格 * sumB[idx]; // 購入に必要な金額は,サイクルとともに徐々に蓄積されます. (....注文量配列を1つずつ購入...)
if (BuyFirst) { // ハンドリングは最初に購入する
if (_N(needMoney) <= _N(account.Balance)) { //グリッドが口座に存在する金額よりも少ないお金を必要とする場合
actualNeedMondy = needMoney; // 必要な実際の金額に割り当てられます
actualNeedStocks = needStocks; // 必要なコインの実際の数に割り当てます.何か問題がありますか?
canNum++; // 利用可能なグリッドの累積数
} else { // _N(needMoney) <= _N(account.Balance) この条件を満たしていない場合は,資金不足タグ変数を true に設定します
notEnough = true (notEnough = true) とは true (真実) です
{ \ pos (192,220) }
{ else } { / else } 販売を最初に扱う
if (_N(needStocks) <= _N(account.Stocks)) { // 必要なコインの数が口座に存在するコインの数よりも少ないかどうかを確認します
actualNeedMondy = needMoney; // 割り当て
actualNeedStocks = needStocks (実際の必要ストック = 必要ストック)
canNum++; // 利用可能なグリッドの累積数
{ \ a1 \ a1 } 他に { \ a2 \ a2 }
notEnough = true; // 資金提供条件が満たされていない場合は true を設定します
{ \ pos (192,220) }
{ \ pos (192,220) }
fishTable[idx] = STATE_WAIT_OPEN; // 現在のインデックス idx に基づいて,グリッドオブジェクトの idx メンバー (グリッドノード) の状態を設定します.
// 初期に STATE_WAIT_OPEN (ポジションを開くのを待っています)
uuidTable[idx] = -1; // 数値化されたオブジェクトは,現在の idx をベースに,独自の idx 値 (fishTable に対応するノード) を -1 に初期化します.
{ \ pos (192,220) }
if (!EnableAccountCheck && (canNum < AllNum)) { // If the funds check is not enabled, and the number of grids (the total number of nodes) ノードが小さいグリッドの数 (ノードの総数) を表示する
// インターフェースパラメータ設定を開くことができます.
ログ (警告,現在の資金のみ作成できます), ネットワークの数, ネットワークの総需要, (最初に購入する? 資金が必要です: ストックが必要です), 十分な資金を保持してください). // ログは警告メッセージを出力します.
canNum = AllNum; // インターフェースパラメータの開示可能な設定の数を更新する
{ \ pos (192,220) }
if (BuyFirst) { //最初に購入する
if (EnableProtectDiff && (FirstPrice - ticker.Sell) > ProtectDiff) { // スプレッド・プロテクションを開いて,現在の入札価格を引いて市場価格を入力します.
市場への参入価格保護
throw
var trader = new Trader(); // Constructs a Trader object, assigning it to the trader variable declared here.
var OpenFunc = BuyFirst ? exchange.Buy : exchange.Sell; // According to whether to buy and sell first, set the open function OpenFunc to refer to exchange.Buy or exchange.Sell
var CoverFunc = BuyFirst ? exchange.Sell : exchange.Buy; // same as above
if (EnableDynamic) { // Set OpenFunc/CoverFunc again according to whether the interface parameter EnableDynamic is enabled.
OpenFunc = BuyFirst ? trader.Buy : trader.Sell; // The member function Buy that references the trader object is used for dynamic pending orders (mainly because
// some exchanges limit the number of pending orders, so virtual dynamic pending orders are required)
CoverFunc = BuyFirst ? trader.Sell : trader.Buy; // same as above
}
var ts = new Date(); // Create a time object at this time (assigned to ts) to record the time at the moment.
var preMsg = ""; // Declare a variable to record the last message, the initial set to empty string
var profitMax = 0; // Maximum return
while (true) { // The main logic after the grid is casted
var now = new Date(); // Record the time when the current cycle started
var table = null; // Declare a variable
if (now.getTime() - ts.getTime() > 5000) { // Calculate whether the difference between the current time now and the recorded time ts is greater than 5000 milliseconds
if (typeof(GetCommand) == 'function' && GetCommand() == "Receiving grid") { // Check if the strategy interaction control command "receives the grid" is received,
// stops and balances to the initial state.
Log("Start executing commands to perform grid operations"); // Output information
balanceAccount(orgAccount, InitAccount); // Perform a balancing function to balance the number of coins to the initial state
return false; // This time the grid function is fishing and return false
}
ts = now; // Update ts with current time now for next comparison time
var nowAccount = _C(exchange.GetAccount); // Declare the nowAccount variable and initially been set as the current account information.
var ticker = _C(exchange.GetTicker); // Declare the ticker variable and initially been set as the current market information.
if (EnableDynamic) { // If you enable dynamic pending orders
trader.Poll(ticker, DynamicMax); // Call the Poll function of the trader object to detect and process all orders based on the
// current ticker market and the interface parameter DynamicMax.
}
var amount_diff = (nowAccount.Stocks + nowAccount.FrozenStocks) - (InitAccount.Stocks + InitAccount.FrozenStocks); // Calculate the current coin difference
var money_diff = (nowAccount.Balance + nowAccount.FrozenBalance) - (InitAccount.Balance + InitAccount.FrozenBalance); // Calculate the current money difference
var floatProfit = _N(money_diff + (amount_diff * ticker.Last)); // Calculate the current floating profit and loss of this time of casting grid
var floatProfitAll = _N((nowAccount.Balance + nowAccount.FrozenBalance - orgAccount.Balance - orgAccount.FrozenBalance) + ((nowAccount.Stocks + nowAccount.FrozenStocks
- orgAccount.Stocks - orgAccount.FrozenStocks) * ticker.Last));
// Calculate the overall floating profit and loss
var isHold = Math.abs(amount_diff) >= exchange.GetMinStock(); // If the absolute value of the coin difference at this moment is greater than the minimum trading
// volume of the exchange, it means that the position has been held.
if (isHold) { // If you have already held a position, execute the setBusy() function, which will update the LastBusy time.
setBusy(); // That is, after opening the position, the opening of the opening mechanism is started.
}
profitMax = Math.max(floatProfit, profitMax); // Refresh the maximum floating profit and loss
if (EnableAccountCheck && EnableStopLoss) { // If you initiate account detection and start a stop loss
if ((profitMax - floatProfit) >= StopLoss) { // If the maximum floating profit or loss minus the current floating profit or loss is greater than or equal to
// the maximum floating loss value, execute the code inside the curly braces
Log("Current floating profit a