バイオスとJavaScriptで遊ぶ - 買い物をするパートナーを作る (6) ロボットが使ったツールコードを開発する

作者: リン・ハーン小さな夢, 作成日: 2017-03-15 11:22:52, 更新日: 2017-10-11 10:37:43

古い白人とJavaScriptで遊んで,買い物をするパートナーを作りました.


ロボット開発の過程で多くの小さなコード片段が蓄積され,そのいくつかは自分の定量化戦略プログラムに借用することができます.

  • 任意のK線周期を変換する

    このコードモジュールは,クラスバックリとして書かれていない,ただ関数を書いているだけで,後期に修正し拡張することも便利である. その役割は,特定の周期の基礎K線データに基づいて,大きな周期を合成するK線である. 通常の市場を見たり,またはプラットフォームの策略を書いているとき,デフォルトは,通常使用される周期のK線である. 例えば1日,1時間,1分,など. 他の周期のデータ,例えば4時間,6時間,8時間のK線を処理する必要がある場合は,自分で手動する必要があります. だからこれを書いた. ソースアドレス:https://www.fmz.com/strategy/35986

    // K线周期合成  扩展为 根据基础K线 合成 为任意周期。
    

var cloneObj = function ((obj) { // ディープコピーオブジェクト関数 var str, newobj = obj.constructor === Array? [] : {}; if (typeof obj!== object) { 返信する JSONのJSONのJSONのJSONは, str = JSON.stringify ((obj); // シリアル化オブジェクト newobj = JSON.parse ((str); // 再現する { else } { ほかに } for (var i in obj) { 変数について newobj[i] = typeof obj[i] === object? cloneObj ((obj[i]) : obj[i]; コメントを表示する {cH00ffff} {cH00ffff} return newobj を表示する (笑) ありがとうございました. var DAY = 0; ワール HOURS = 1; と表示される. var isFirstFind = true; var ファーストスタンプ = null; ありがとうございました. function GetDHM ((objTime,BaseCycle,NewCycleForMS) { は,この関数について, 変数式は, if ((BaseCycle % (1000 * 60 * 60 * 24) === 0) { ret[0] = objTime.getDate ((()); ret[1] = DAY; }else if ((BaseCycle % (1000 * 60 * 60) === 0) { ret[0] = objTime.getHours (()); ret[1] = HOURS; }else if ((BaseCycle % (1000 * 60) === 0) { ret[0] = objTime.getMinutes (※); ret[1] = MINUTES; {cH00ffff} if ((NewCycleForMS % (1000 * 60 * 60 * 24) === 0) { ret[2] = DAY; }else if ((NewCycleForMS % (1000 * 60 * 60) === 0) { ret[2] = HOURS; }else if ((NewCycleForMS % (1000 * 60) === 0) { ret[2] = MINUTES; {cH00ffff} 返信 ret; {cH00ffff} ありがとうございました. フォローしているファイルは, if(ret[1] === DAY && ret[2] === DAY) { var array_day = []; 任意の数列を表示する for ((var i = 1 ; i < 29; i += (NewCycleForMS / BaseCycle)) { array_day.push ((i) について {cH00ffff} for ((var j = 0 ; j < array_day.length; j++ ) { if(ret[0] === array_day[j]) { 返信する {cH00ffff} {cH00ffff} }else if(ret[1] === HOURS && ret[2] === HOURS) { 任意の時間帯を表示します. for ((var i = 0 ; i < 24; i += (NewCycleForMS / BaseCycle)) { array_hours.push ((i) について {cH00ffff} for ((var j = 0 ; j < array_hours.length ; j++) { if ((ret[0] === array_hours[j]) { 返信する {cH00ffff} {cH00ffff} }else if(ret[1] ===MINUTES && ret[2] ===MINUTES) { var array_minutes = []; for ((var i = 0; i < 60; i += (NewCycleForMS / BaseCycle)) { array_minutes.push (i) について {cH00ffff} for ((var j = 0; j < array_minutes.length; j++) { if ((ret[0] === array_minutes[j]) { 返信する {cH00ffff} {cH00ffff} ほら throw 目標周期とベース周期が一致しない! 目標周期ミリ秒数: + NewCycleForMS + " ベース周期ミリ秒数: " + BaseCycle; {cH00ffff} {cH00ffff} ありがとうございました. function Calc_High ((AssRecords, n,BaseCycle,NewCycleForMS) { 計算する var max = AssRecords[n].High; for ((var i = 1 ; i < NewCycleForMS / BaseCycle; i++) { 計算の3つの要素は,次の2つです. {cH00ffff} 返回max {cH00ffff} ありがとうございました. function Calc_Low ((AssRecords, n,BaseCycle,NewCycleForMS) { 計算する var min = AssRecords[n].Low; for ((var i = 1 ; i < NewCycleForMS / BaseCycle; i++) { 低,min = Math.min ((AssRecords[n + i].Low,min); {cH00ffff} 返信する時間 {cH00ffff} ありがとうございました. function AssembleRecords ((records, NewCycleForMS) { は,この関数で表示されている. var AssRecords = records.slice(0); // ディープコピー var AfterAssRecords = [];

if(!records || records.length < 2){
    throw (!records) ? "传入的records参数为 错误" + records : "基础K线长度小于2";
}
var BaseCycle = records[records.length - 1].Time - records[records.length - 2].Time;
if(NewCycleForMS % BaseCycle !== 0){
    throw "目标周期‘" + NewCycleForMS + "’不是 基础周期 ‘" + BaseCycle + "’ 的整倍数,无法合成!";
}
if(NewCycleForMS / BaseCycle > records.length){
    throw "基础K线数量不足,请检查是否基础K线周期过小!";
}

// 時間軸を判定し,基線Kの開始時刻を目標線Kの開始時刻と比較して探します. var objTime = new Date (((); この項目は, for (var i = 0; i < AssRecords.length; i++) { オブジェタイム.セットタイム ((AssRecords[i].Time); var ret = GetDHM ((objTime,BaseCycle,NewCycleForMS));

    if (isFirstFind === true && SearchFirstTime(ret, BaseCycle, NewCycleForMS) === true) {
        FirstStamp = AssRecords[i].Time;
        for (j = 0; j < i; j++) {
            AssRecords.shift();        // 把目标K线周期前不满足合成的数据排除。
        }
        isFirstFind = false;
        break;                         // 排除后跳出
    }else if(isFirstFind === false){
        if((AssRecords[i].Time - FirstStamp) % NewCycleForMS === 0){
            for (j = 0; j < i; j++) {
                AssRecords.shift();    // 把目标K线周期前不满足合成的数据排除。
            }
            break;
        }
    }
}
var BarObj = {                         // 定义一个 K线柱结构
    Time: 0,
    Open: 0,
    High: 0,
    Low: 0,
    Close: 0,
    Volume: 0,
};
var n = 0;
for (n = 0; n < AssRecords.length - (NewCycleForMS / BaseCycle); n += (NewCycleForMS / BaseCycle)) {     // 合成
    /*
    {
    Time    :一个时间戳, 精确到毫秒,与Javascript的 new Date().getTime() 得到的结果格式一样
    Open    :开盘价
    High    :最高价
    Low :最低价
    Close   :收盘价
    Volume  :交易量
    }
    */
    BarObj.Time = AssRecords[n].Time;
    BarObj.Open = AssRecords[n].Open;
    BarObj.High = Calc_High(AssRecords, n, BaseCycle, NewCycleForMS); 
    BarObj.Low =  Calc_Low(AssRecords, n, BaseCycle, NewCycleForMS); 
    BarObj.Close = AssRecords[n + (NewCycleForMS / BaseCycle) - 1].Close;
    BarObj.Volume = AssRecords[n + (NewCycleForMS / BaseCycle) - 1].Volume;
    AfterAssRecords.push(cloneObj(BarObj));
}

BarObj.Time = AssRecords[n - (NewCycleForMS/BaseCycle) ].Time + NewCycleForMS; // 最後の時間は変更できません. BarObj.Open = AssRecords[n].Open; BarObj.Open = AssRecords[n].Open; BarObj.Open = AssRecords[n].Open; BarObj.Open = AssRecords[n].Open; BarObj.Open = AssRecords[n].Open; BarObj.Open = AssRecords[n].Open; BarObj.Open = AssRecords[n].Open; バール・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ・オブ BarObj.Close = AssRecords [AssRecords.length - 1].Close; BarObj.Volume = AssRecords[AssRecords.length - 1].Volume; ファイルファイル: ファイルファイル: ファイルファイル: ファイルファイル: ファイルファイル: var max = AssRecords[n].High; var min = AssRecords[n].Low; for ((var index_n = n + 1 ;index_n < AssRecords.length; index_n++) { 計算機は,数値値で,数値で,数値で 低値で計算される数値です. {cH00ffff} BarObj.High = max; BarObj.Low = min; AfterAssRecords.push ((cloneObj ((BarObj))));

return AfterAssRecords;

ありがとうございました. ありがとうございました. function main() { // テストコード ワイルド・オブ・ザ・ウィズexchange.IO(status) (状態) { ログステータス (LogStatus) {cH00ffff} var Info = _C ((exchange.SetContractType,MA705); // 試験用メタロール705契約のK線データ合成 var records = exchange.GetRecords (※) を表示する while (!records の長さ < 24) { records = exchange.GetRecords (※) を取得する {cH00ffff}
// インタフェースのパラメータを処理します. var Num_UI_NewCycleForMS = 1 について var arrayNum = UI_NewCycleForMS.split (("*"); for ((var indexNum = 0 ; indexNum < arrayNum.length ; indexNum++) { Num_UI_NewCycleForMS = Num_UI_NewCycleForMS * 番号 (arrayNum[indexNum]); {cH00ffff} Log ( 設定周期ミリ秒の時間:,Num_UI_NewCycleForMS)
while (true) { と表示する records = _C (exchange.GetRecords); // Log ( 原 K 線データ:長さ, records.length,データ:, records); records = AssembleRecords ((records, Num_UI_NewCycleForMS); // 最初のパラメータはベースKラインで,第二のパラメータは変換される周期のミリ秒数で,1000 * 60 * 20は20分に変換されます. // Log (変換後K行データ:長度, records.length,データ:, records); $PlotRecords ((records, BTC); $PlotRecords (レコード, BTC); $PlotRecords (レコード, BTC); / throw stop ; / ceshi 投げ ストップ ; スリープ ((1000); ありがとうございました. ありがとうございました.


- #### 2、传统期货差价监控 (CTP)

当需要分析两个品种差价走势的时候,会用上这段代码。有时候也会把这段代码修改集成到自己的策略程序里面(比如跨期对冲策略),代码会绘制出一个差价走势图,在学习如何让机器人程序画图也是很有帮助的,很好的例子。
源码地址: https://www.fmz.com/strategy/5379

var __lastDiff = 0; var __AType = [Last,Buy,Sell][AType]; var __BType = [Last,Buy,Sell][BType]; ありがとうございました. この関数で, if (typeof(precision)!= ) { 精度 = 4 ありがとうございました. var d = parseFloat ((v.toFixed ((Math.max ((10, precision + 5))); s = d.toString (().split ((""); if (s.length < 2つの s[1].length <= precision) { return d: 返却する ありがとうございました. ありがとうございました. 精度 (precision) を計算する. return Math.floor ((d * b) / b) について ありがとうございました. ありがとうございました. この関数で, ワール while (!(r = method.apply ((this, Array.prototype.slice.call ((arguments).slice ((1))) { スリープ (interval) ありがとうございました. 返回する ありがとうございました. ありがとうございました. この関数は, var a = EnsureCall ((exchange.SetContractType,AInstrument) について) var ticker A = 保証コール (exchange.GetTicker) var b = 保証コール (exchange.SetContractType,BInstrument) var tickerB = 保証コール (exchange.GetTicker) var diff = _N (ticker A[__AType] - ticker B[__BType]); LogStatus ((a.InstrumentName, _N ((tickerA[__AType]), b.InstrumentName, _N ((tickerB[__BType]), 値: , diff); この式は,この式を if (Math.abs(Math.abs(diff) - Math.abs(__lastDiff)) > 200) { 返信する ありがとうございました. ありがとうございました. この式は,この式を // add は,series にデータを追加する.パラメータ形式は[series シリアル番号,データ]; __chart.add (([0, [new Date (().getTime ((), diff))); __lastDiff = diff; ありがとうございました. ありがとうございました. ありがとうございました. main ((() {の関数について if (exchange.GetName().indexOf(Futures_CTP) == -1) { 投機は,従来の先物 (CTP) のみをサポートします. ありがとうございました. SetErrorFilter ((loginで済んで流量制御で接続が失敗したタイムアウトタグ); // Chart 函数に伝達されるものは,文脈に関係のない構造物である必要があります. (HighStocks のルール,詳細参数,HighStocks の使い方) __chart = Chart (チャート) ツールチップ: { xDateFormat: %Y-%m-%d %H:%M:%S, %A {a1pos (114,268) } タイトル: text: 価格分析図 {a1pos (114,268) } rangeSelector: { 選択する [ボタンを押す] 時間 カウント: 1 text: 1h {a,b,c} 時間 カウント: 3 text: 3h {a,b,c} 時間 8つ数える text: 8h {a,b,c} タイプ: all text: All (笑) selected: 0 選択された: 0 inputEnabled: false インプット可能 {a1pos (114,268) } x軸: { type: 日付時間タグ {a1pos (114,268) } y軸: { ストローク 値: NormalDiff カラー: 緑の dashStyle (ダッシュスタイル): shortdash width: 1 について {a,b,c} 値:HighDiff カラー:赤 dashStyle (ダッシュスタイル): shortdash width: 1 について {a,b,c} 値: - 標準差, カラー: 緑の dashStyle (ダッシュスタイル): shortdash width: 1 について {a,b,c} 値: -HighDiff カラー:赤 dashStyle (ダッシュスタイル): shortdash width: 1 について {cH00ffff} {a1pos (114,268) } シリーズ: [{ name: の価格が下がる 詳細はこちら ツールチップ: { 値デシマルは 2 ありがとうございました. {cH00ffff} ) // reset すべてのグラフ前の情報を削除します // __chart.reset ((()); var a = EnsureCall ((exchange.SetContractType,AInstrument) について) var b = 保証コール (exchange.SetContractType,BInstrument) Log ((a.InstrumentName + . + __AType, -, b.InstrumentName + . + __BType, の差が収益として表示されるグラフの); TickInterval = Math.max ((TickInterval, 50)); ティックインターバル = Math.max (ティックインターバル, 50)); インターバル = Math.max ((Interval, 50); 文字列を表示します. チェックをしてください. スリープ (TickInterval) ありがとうございました. ありがとうございました.


- #### 3、CTP手动全平CTP商品期货持仓

在Simnow 上测试 商品期货策略时经常需要把已经开过的仓位平掉重新测试代码,这样就需要个类似一键平仓的程序来处理 恢复模拟账号未开仓状态。这里使用了一个交易处理模块: $.NewPositionManager 就是该模块的接口函数,作用是生成一个对象,可以调用该对象的方法处理具体操作,比如 全平仓: CoverAll(); 。  做了一点额外的功能,在全部平仓完以后,会打印出所有交易的标的物名称。

var p = $.NewPositionManager (新位置管理者) "; 機能 main ((() { 真実である もしexchange.IOこの状態は, p.CoverAll ((()); var positions = _C ((exchange.GetPosition) ); if ((positions.length === 0) { ログ (positions is:, positions); ブロンクス: {cH00ffff} ほら ログステータス (サーバーに接続されていない,待ち中) {cH00ffff} スリープ (2000年) {cH00ffff} ワルディクト =exchange.IO("instruments"); // 取引所のすべての商品のリストを{商品名: 詳細}辞書形式に戻す for ((var k in dict) { 変数から変数に変換する) Log ((製品名:,k, 詳細情報: 製品名:, dict[k]); {cH00ffff} ログ (exit., _C (exchange.GetPosition)); {cH00ffff}

  
- #### 4、商品期货主力合约过滤

  在处理商品期货合约的连续性时会遇到主力合约的问题,如何更快的过滤识别出主力合约呢? 同样也写了个代码模块,可以改造,嵌入,或者单独使用。
  在 filter 变量中指定要 扫描的合约代码头。(即不含日期信息的合约代码的部分)  
    

変数値が 0 になります. 変数列は, main ((() {の関数について var filter = [MA,CF,zn,SR,pp,l,ni,i,v,jm,al,jd,cs,p]; var products = []; 取引サーバーへの接続を待っています. ワイルド・ウィンドウexchange.IO(Sleep ((1000)); スリープ (Sleep ((1000)); ログ (はすべての契約を入手し始めた) var instruments = _C(exchange.IOinstruments) とも呼ばれています. ログ (契約リスト取得成功) 変数について説明します for (var instrumentId in instruments) { 変数について len++; {cH00ffff} 契約のリストの長さは:,len) for (var instrumentId in instruments) { 変数について if (instruments[instrumentId].IsTrading) { は,この2つの関数で割り切れます. var found = false; for (var i = 0; i < filter.length; i++) { if (instruments[instrumentId].ProductID ==フィルター[i]) { 発見 = true; ありがとうございました. {cH00ffff} if (!found) { を表示する フォローする {cH00ffff} if (typeof(products[instruments[instrumentId].ProductID]) === undefined) { products[instruments[instrumentId].ProductID] = []; 製品IDは,このリストに含まれています. ありがとうございました. products[instruments[instrumentId].ProductID].push ((instrumentId) ]は,プロダクトIDを表示している. ありがとうございました. ありがとうございました. for (var product in products) { 商品の種類について var ss = products[product]; var ss = 製品 (製品) について Log ((購読,product,,ss.length,種契約,主力契約を識別するために); ワル・ボル=0 volIdx = 0; for (var i = 0; i < ss.length; i++) { _C ((exchange.SetContractType, ss[i]); 契約型を設定する {cH00ffff} スリープ ((5000); for (var i = 0; i < ss.length; i++) { _C ((exchange.SetContractType, ss[i]); 契約型を設定する var ticker = exchange.GetTicker ((() と表示されている.

        if (ticker) {
            var obj = JSON.parse(exchange.GetRawJSON());
            if (obj.OpenInterest > vol) {
                vol = obj.OpenInterest;
                volIdx = i;
            }
        }
    }
    // 取消订阅行情(之后此合约K线将停止收集), 当然也可以不取消, 这里演示用
    for (var i = 0; i < ss.length; i++) {
        _C(exchange.SetContractType, "-" + ss[i]);
    }
    strArray.push(ss[volIdx]);
    Log("主力合约为", ss[volIdx], "持仓", vol, '#ff0000');
}
for(var i = 0 ; i < strArray.length; i++){
    str += strArray[i] + ',';
}
Log("主力合约:", str);

}


- #### 5、交互模块

  有时候需要给机器人交互,需要下命令、改参数、获取详细运行状态参数 就需要交互代码了。
  

function get_Command() {// インタラクションを担当する関数,インタラクションをタイムリー更新する.関連する数値,熟悉したユーザが自力で拡張することができます. var keyValue = 0;// コマンドが送信したパラメータ 数値 変数で表示する var cmd = GetCommand ((); //取得 インタラクティブコマンド API if (cmd) { を表示する ログ (ボタンを押すと: ログ,cmd);//ログが表示される この関数は,JSON を理解したいので,ここで処理したトラブルは終わりました. // は,文字列を処理し,函数に戻す文字列を: で2つの文字列に分割します.

  if(arrStr.length === 2){//接受的不是 按钮型的,是数值型。
      jsonObjStr = '{' + '"' + arrStr[0] + '"' + ':' + arrStr[1] + '}'; // 把 字符串数组中的元素重新 
                                                                        //拼接 ,拼接成 JSON 字符串  用于转换为JSON 对象。
      jsonObj = JSON.parse(jsonObjStr); // 转换为JSON 对象

      for(var key in jsonObj){ // 遍历对象中的  成员名
          keyValue = jsonObj[key]; //取出成员名对应的 值 , 就是交互按钮的值
      }

      if(arrStr[0] == "upDateAmount"){// 此处为 数字型  。这里处理分为  按钮  和  数字型  。 详见 策略参数 设置界面 下的 交互设置
          way = 1;
      }
      if(arrStr[0] == "扩展1"){
          way = 2;
      }
      if(arrStr[0] == "扩展2"){
          way = 3;
      }
      if(arrStr[0] == "扩展3"){
          way = 4;
      }
  }else if(arrStr.length === 1){// 此处为 按钮型  
      //路由
      if(cmd == "cmdOpen"){ 
          way = 0;
      }
      if(cmd == "cmdCover"){
          way = 5;
      }
  }else{
      throw "error:" + cmd + "--" + arrStr;
  }
  switch(way){ // 分支选择 操作
      case 0://处理 发出开仓信号
          tiaojian = 1;
          break;
      case 1://处理
          Amount = keyValue;//把交互界面设置的 数值 传递给 Amount
          Log("开仓量修改为:",Amount);//提示信息
          break;
      case 2://处理

          break;
      case 3://处理

          break;
      case 4://处理

          break;
      case 5://处理 发出平仓信号
          tiaojian = 2;
          break;
      default: break;
  }

} }


  有时我们甚至需要在机器人运行时插入运行JS 代码:

var cmd = GetCommand ((); // API を呼び出し,インターフェースインタラクティブコントローラのメッセージを取得します. if (cmd) { // メッセージがあるかどうかを判断する var js = cmd.split ((:, 2) [1]; // 分割 返したメッセージ 文字列, 2 を返し,インデックスの要素を 1 にする.js という変数に値を与える. Log (( 実行 デューグコード:, js); // 出力 実行コード try { // 異常を検出する eval ((js); //は,入力されたパラメータ ((コード) を実行する eval関数を実行します. } catch(e) { // 異常を投げる Log ((Exception, e); // エラーメッセージを出力 {cH00ffff} {cH00ffff}




当然还有很多代码工具尽在 : https://www.fmz.com/square


#### 先写到这,欢迎读者给我留言!提出建议和意见,如果感觉好玩可以分享给更多热爱程序热爱交易的朋友 
https://www.fmz.com/bbs-topic/735

### 程序员 littleDream 原创

もっと