この記事の目的は,戦略開発におけるいくつかの経験や,読者が迅速に取引戦略開発の重要な点を把握できるようにするいくつかのヒントを記述することです.
戦略の設計で似たような細かいことを目にすると すぐに合理的な解決策を思いつくことができます
FMZ Quantプラットフォームは 説明やテスト,練習の例として使っています
戦略 プログラミング言語 JavaScript を使用します
取引対象としてブロックチェーン資産市場 (BTC,ETHなど) を対象としています
通常,戦略論理に応じて,以下の異なるインターフェースを使用して市場データを取得することができます. ほとんどの戦略論理は市場データによって動きます (もちろん,固定投資戦略のような価格データに関心のない戦略もあります).
GetTicker: リアルタイムで チェック引数を取得します
通常は,現在の最新価格を迅速に取得するために使用されます.
注文簿の注文深さを取得する 一般に,オーダーブック深さの各層の価格と待機中のオーダーのサイズを取得するために使用されます.ヘッジ戦略,市場構築戦略などに使用されます.
GetTrade: 最新の取引記録を取得します. 一般的には,短時間周期で市場行動を分析し,市場の微小変化を分析するために使用されます.通常は高周波戦略やアルゴリズム戦略に使用されます.
GetRecords:市場K線データを取得する.通常,トレンド追跡戦略や指標の計算に使用される.
戦略を設計する際に,初心者は通常,様々なエラーを無視し,戦略の各部分の結果が確立されていると直感的に信じている.しかし,それは真実ではありません. 戦略プログラムの動作において,市場データを要求する際に,あなたはさまざまな予期せぬ状況に直面します.
例えば,いくつかの市場インターフェースは,実行されていないデータを返します.
var depth = exchange.GetDepth()
// depth.Asks[0].Price < depth.Bids[0].Price "Selling 1" price is lower than "buying 1" price, this situation cannot exist on the market.
// Because the selling price is lower than the buying price, the order must have been executed.
// depth.Bids[n].Amount = 0 Order book buying list "nth" layer, order quantity is 0
// depth.Asks[m].Price = 0 Order book selling list "mth" layer, the order price is 0
または直接 exchange.GetDepth() で null を返します.
このような奇妙な状況が多くあります.したがって,これらの予測可能な問題に対処することが必要です.このような処理スキームは,障害耐性処理と呼ばれます.
誤りに対処する通常の方法は データを捨てて再取得することです
例えば:
function main () {
while (true) {
onTick()
Sleep(500)
}
}
function GetTicker () {
while (true) {
var ticker = exchange.GetTicker()
if (ticker.Sell > ticker.Buy) { // Take the example of fault-tolerant processing that detects whether the "Selling 1" price is less than the "Buying 1" price.
// Exclude this error, the current function returns "ticker".
Return ticker
}
Sleep(500)
}
}
function onTick () {
var ticker = GetTicker() // Make sure the "ticker" you get doesn't exist the situation that "Selling 1" price is less than the "Buying 1" price.
// ... specific strategy logic
}
予測可能な他の故障耐性プロセスでも同様のアプローチが用いられる.
戦略の論理を動かすために 間違った論理を使うことは 決してできません
K線データ取得,呼び出し:
var r = exchange.GetRecords()
取得したK線データは,次のような配列です.
[
{"Time":1562068800000,"Open":10000.7,"High":10208.9,"Low":9942.4,"Close":10058.8,"Volume":6281.887000000001},
{"Time":1562072400000,"Open":10058.6,"High":10154.4,"Low":9914.5,"Close":9990.7,"Volume":4322.099},
...
{"Time":1562079600000,"Open":10535.1,"High":10654.6,"Low":10383.6,"Close":10630.7,"Volume":5163.484000000004}
]
時間,開通価格,最高価格,最低価格,閉店価格,およびボリュームを含んでいます.
これはK線バーです. 一般的なK線データは移動平均値,MACDなどの指標を計算するために使用されます.
K線データはパラメータ (原材料データ) として渡され その後指標パラメータが設定され 指標データの関数を計算します これを指標関数と呼びます
FMZ Quantの定量取引プラットフォームには 多くの指標機能があります
例えば,移動平均指標を計算します. 通過したK線データのサイクルに基づいて,対応サイクルの移動平均を計算します.
例えば,通過するK線データ (1つのK線バーは1日を表す) は,日平均線を計算します.同じことです.通過する平均指標関数のK線データが1時間のサイクルである場合,計算された指標は1時間の移動平均線です.
5日間の移動平均指標を計算したい場合は,まず毎日K線データを準備します.
var r = exchange.GetRecords(PERIOD_D1) // Pass parameters to the "GetRecords" function "PERIOD_D1" specifies the day K line to be acquired.
// Specific function using method can be seen at: https://www.fmz.com/api#GetRecords
5日間の移動平均を計算したい場合は, インディケーター関数の指標パラメータを 5 に設定する必要があります.
var ma = TA.MA(r, 5) // "TA.MA()" is the indicator function used to calculate the moving average indicator. The first parameter sets the daily K-line data r just obtained.
// The second parameter is set to 5. The calculated 5-day moving average is the same as the other indicators.
5日間の移動平均を計算するにはどうすればいいですか? 移動平均を計算するには,
答えは,何もできないことだ.
移動平均指標は K線バーの閉店価格の平均値だからです
したがって,K線データと指標関数を使用して指標データを計算する前に,K線データ内のK線バーの数が指標計算条件 (指標パラメータ) を満たしているか確認する必要があります.
5日間の移動平均を計算する前に,まず確認する必要があります. 完全なコードは以下のとおりです.
function CalcMA () {
var r = _C(exchange.GetRecords, PERIOD_D1) // _C() is a fault-tolerant function, the purpose is to avoid r being null, you can get more information at: https://www.fmz.com/api#_C
if (r.length > 5) {
Return TA.MA(r, 5) // Calculate the moving average data with the moving average indicator function "TA.MA", return it as a function return value.
}
Return false
}
function main () {
var ma = CalcMA()
Log(ma)
}
バックテスト表示:
[null,null,null,null,4228.7,4402.9400000000005, ... ]
5日間の移動平均指標が表示されます. 最初の4つはゼロです. K線バーの数が5未満なので,平均は計算できません. 5日目のK線バーに達すると,それを計算できます.
ストラテジーは,K線サイクルが完了したとき,いくつかの操作を処理するか,またはいくつかのログをプリントする必要があります.
プログラミングの経験のない初心者にとっては,これは厄介な問題かもしれません. ここでは解決策を提示します.
K線バーサイクルが完了すると判断する方法.K線データのタイム属性から始めることができます.K線データを入手するたびに,このK線データの最後のK線バーのタイム属性が変化するか否かを判断します.変更された場合,新しいK線バーが生成されたことを意味します (新しく生成されたK線バーの前のK線バーサイクルが完了したことを証明します),変更がない場合は,新しいK線バーが生成されていないことを意味します (現在の最後のK線バーサイクルはまだ完了していません).
K線データの最後のK線バーの時間を記録する変数が必要です
var r = exchange.GetRecords()
var lastTime = r[r.length - 1].Time // "lastTime" used to record the last K-line bar time.
実際には,通常はこうです.
function main () {
var lastTime = 0
while (true) {
var r = _C(exchange.GetRecords)
if (r[r.length - 1].Time != lastTime) {
Log ("New K-line bar generated")
lastTime = r[r.length - 1].Time // Be sure to update "lastTime", this is crucial.
// ... other processing logic
// ...
}
Sleep(500)
}
}
逆テストでは,K線サイクルは,日数に設定されています (パラメータは,exchange.GetRecords
機能が呼び出され,バックテストに従って設定されたK線サイクルがデフォルトパラメータです).新しいK線バーが表示されるたびに,ログをプリントします.
ストラテジーのインターフェースにアクセスするのにかかる時間について 特定の表示または制御が欲しくなったら,次のコードを使用できます.
function main () {
while (true) {
var beginTime = new Date().getTime()
var ticker = exchange.GetTicker()
var endTime = new Date().getTime()
LogStatus(_D(), "GetTicker() function time-consuming:", endTime - beginTime, "millisecond")
Sleep(1000)
}
}
簡単に言うと,時間スタンプは,呼び出し後に記録GetTicker
呼び出し前のタイムスタンプから減算し,経験したミリ秒の数を計算します.GetTicker
実行から返還まで
例えば,販売注文の処理では,販売注文の金額は口座にあるコインの数を超えてはならない. 口座にあるコインの数よりも多い場合は 順序がエラーになります
制御する方法はこうです
例えば0.2コインを短売りします
var planAmount = 0.2
var account = _C(exchange.GetAccount)
var amount = Math.min(account.Stocks, planAmount)
この方法により,注文数が口座に存在するコインの数を超えないようにします.
同じ理由でMath.max
値の下限を確保するために使用されます.
通常,通常の交換には,特定の取引対の最低送信オーダー制限があります.最低金額を下回れば,注文は拒否されます.これはプログラム失敗を引き起こします.
BTCは通常 0.01 の最小のプレッシングオーダーの量を持っていると仮定します.
取引戦略は,時には 0.01 未満の注文量をもたらすことができますので,我々は使用することができますMath.max
最低の注文量を確保するためです
精度を制御するには_N()
機能やSetPrecision
function.
についてSetPrecision()
この関数は1回だけ設定され,注文量と価格値の小数点数はシステム内で自動的に切断されます.
について_N()
機能は,ある値に対して小数点切断 (精度制御) を行うことです.
例えば:
var pi = _N(3.141592653, 2)
Log(pi)
3 桁の小数点に割って,小数点を2つ残します. 3.14
詳細については API 文書を参照してください.
このメカニズムを使用して,タイムスタンプ検出方法を使用して,予定されたタスクが実行された最後の時のタイムスタンプをマイナスした現在のタイムスタンプを決定し,リアルタイムで経過した時間を計算できます.経過した時間が一定の設定時間長さを超えると.その後,新しい操作を実行します.
例えば固定投資戦略で使われます
var lastActTime = 0
var waitTime = 1000 * 60 * 60 * 12 // number of milliseconds a day
function main () {
while (true) {
var nowTime = new Date().getTime()
if (nowTime - lastActTime > waitTime) {
Log ("Execution Fixed")
// ... specific fixed investment operation, buying operation.
lastActTime = nowTime
}
Sleep(500)
}
}
これは簡単な例です
FMZ 量子を使用する_G()
保存機能を終了すると,保存進捗状態を終了し,自動復元状態を再起動する戦略を設計することが便利です.
var hold = {
Price : 0,
Amount : 0,
}
function main () {
if (_G("hold")) {
var ret = _G("hold")
hold.price = ret.price
hold.amount = ret.amount
Log("restore hold:", hold)
}
var count = 1
while (true) {
// ... strategy logic
// ... In the strategy operation, it is possible that when opening a position, then assign the position price of the open position to "hold.price", and the amount of open positions is assigned to "hold.amount" to record the position information.
hold.price = count++ // simulate some values
hold.amount = count/10 // Simulate some values
Sleep(500)
}
}
function onexit () { // Click the stop button on the robot to trigger the execution of this function. After the execution, the robot stops.
_G("hold", hold)
Log("save hold:", JSON.stringify(hold))
}
このデータから,hold
ロボットが停止するたびに保存されます. そしてデータを再起動するたびに,データが読み取られ,hold
停止前の状態に戻ります
上記は簡単な例です.実際の取引戦略で使用される場合,戦略に復元する必要があるキーデータ (一般的にアカウント情報,ポジション,利益価値,取引方向など) に基づいて設計する必要があります.
復元する条件も設定できます
取引戦略を発展させるためのヒントです.
実践訓練は,自分を向上させる最も速い方法です.皆さんに幸運を祈ります.