avatar of 发明者量化-小小梦 发明者量化-小小梦
フォロー ダイレクトメッセージ
4
フォロー
1271
フォロワー

戦略を段階的に書く方法を教えます - 私の言語戦略を移植する

作成日:: 2019-10-21 14:59:12, 更新日:: 2024-12-17 20:37:18
comments   1
hits   2733

戦略を段階的に書く方法を教えます - 私の言語戦略を移植する

戦略を段階的に書く方法を教えます - 私の言語戦略を移植する

最近、友人と戦略について話していたとき、私の言語を使って戦略を書く人の多くが柔軟性の問題に悩まされていることを知りました。多くの場合、システムで提供されていない標準の K ライン期間を使用する必要があります。たとえば、最も要求される要件は、4 時間の K ラインを使用することです。この問題は記事で解決されています。ご興味があれば、まずはこちらをご覧ください:リンク。しかし、my 言語戦略では、my 言語の高度にカプセル化された性質のため、この問題は単独ではデータを柔軟に処理することができません。このとき、戦略的思考を他の言語に移植する必要があります。

トレンド戦略を移植するのは非常に簡単です。サンプルコードを使用して、駆動戦略のデータ計算部分を入力し、取引シグナルのトリガー条件を入力できます。

再利用可能なサンプルコード:

OKEX 先物に使用される戦略を例に挙げます。

// 全局变量
var IDLE = 0
var LONG = 1
var SHORT = 2
var OPENLONG = 3
var OPENSHORT = 4
var COVERLONG = 5
var COVERSHORT = 6  

var BREAK = 9
var SHOCK = 10  

var _State = IDLE
var Amount = 0                 // 记录持仓数量
var TradeInterval = 500        // 轮询间隔
var PriceTick = 1              // 价格一跳
var Symbol = "this_week"  

function OnTick(){
    // 驱动策略的行情处理部分
    // 待填充...
     
    // 交易信号触发处理部分
    // 待填充...  

    // 执行交易逻辑
    var pos = null
    var price = null
    var currBar = records[records.length - 1]
    if(_State == OPENLONG){
        pos = GetPosition(PD_LONG)
        // 判断是不是 满足状态,如果满足 修改状态
        if(pos[1] >= Amount){
            _State = LONG
            Amount = pos[1]   // 更新实际量
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2
        Trade(OPENLONG, price, Amount - pos[1], pos, PriceTick)                // (Type, Price, Amount, CurrPos, PriceTick)
    }  

    if(_State == OPENSHORT){
        pos = GetPosition(PD_SHORT)
        if(pos[1] >= Amount){
            _State = SHORT
            Amount = pos[1]   // 更新实际量
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2
        Trade(OPENSHORT, price, Amount - pos[1], pos, PriceTick)
    }  

    if(_State == COVERLONG){
        pos = GetPosition(PD_LONG)
        if(pos[1] == 0){
            _State = IDLE
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2
        Trade(COVERLONG, price, pos[1], pos, PriceTick)
    }
    
    if(_State == COVERSHORT){
        pos = GetPosition(PD_SHORT)
        if(pos[1] == 0){
            _State = IDLE
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2
        Trade(COVERSHORT, price, pos[1], pos, PriceTick)
    }
}  

// 交易逻辑部分
function GetPosition(posType) {
    var positions = _C(exchange.GetPosition)
    var count = 0
    for(var j = 0; j < positions.length; j++){
        if(positions[j].ContractType == Symbol){
            count++
        }
    }  

    if(count > 1){
        throw "positions error:" + JSON.stringify(positions)
    }  

    for (var i = 0; i < positions.length; i++) {
        if (positions[i].ContractType == Symbol && positions[i].Type === posType) {
            return [positions[i].Price, positions[i].Amount];
        }
    }
    Sleep(TradeInterval);
    return [0, 0];
}  

function CancelPendingOrders() {
    while (true) {
        var orders = _C(exchange.GetOrders)
        for (var i = 0; i < orders.length; i++) {
            exchange.CancelOrder(orders[i].Id);
            Sleep(TradeInterval);
        }
        if (orders.length === 0) {
            break;
        }
    }
}  

function Trade(Type, Price, Amount, CurrPos, OnePriceTick){    // 处理交易
    if(Type == OPENLONG || Type == OPENSHORT){                 // 处理开仓
        exchange.SetDirection(Type == OPENLONG ? "buy" : "sell")
        var pfnOpen = Type == OPENLONG ? exchange.Buy : exchange.Sell
        var idOpen = pfnOpen(Price, Amount, CurrPos, OnePriceTick, Type)
        Sleep(TradeInterval)
        if(idOpen) {
            exchange.CancelOrder(idOpen)
        } else {
            CancelPendingOrders()
        }
    } else if(Type == COVERLONG || Type == COVERSHORT){        // 处理平仓
        exchange.SetDirection(Type == COVERLONG ? "closebuy" : "closesell")
        var pfnCover = Type == COVERLONG ? exchange.Sell : exchange.Buy
        var idCover = pfnCover(Price, Amount, CurrPos, OnePriceTick, Type)
        Sleep(TradeInterval)
        if(idCover){
            exchange.CancelOrder(idCover)
        } else {
            CancelPendingOrders()
        }
    } else {
        throw "Type error:" + Type
    }
}  

function main() { 
    // 设置合约
    exchange.SetContractType(Symbol)  

    while(1){
        OnTick()
        Sleep(1000)
    }
}

例: 二重移動平均戦略の移植

Mai Languageバックテスト: 戦略を段階的に書く方法を教えます - 私の言語戦略を移植する

Mai言語戦略コード:

MA5^^MA(C,5);
MA15^^MA(C,15);
CROSSUP(MA5,MA15),BPK;
CROSSDOWN(MA5,MA15),SPK;

JavaScriptへの移行戦略

まず、再利用可能なサンプル コードに市場取得と指標計算の部分を入力します。

// 驱动策略的行情处理部分
var records = _C(exchange.GetRecords)  

if (records.length < 15) {
    return 
}  

var ma5 = TA.MA(records, 5)
var ma15 = TA.MA(records, 15)
var ma5_pre = ma5[ma5.length - 3]
var ma15_pre = ma15[ma15.length - 3]
var ma5_curr = ma5[ma5.length - 2]
var ma15_curr = ma15[ma15.length - 2]

ご覧のとおり、二重移動平均戦略は非常にシンプルです。まず K ライン データを取得するだけです。records、その後使用TA函数库移動平均関数TA.MA5日移動平均と15日移動平均を計算します(バックテストインターフェースでKライン期間が日次Kラインに設定されていることがわかりますので、TA.MA(records, 5)5日間の移動平均を計算します。TA.MA(records, 15)15日移動平均)。 そしてma5指標データの最後から2番目のポイントma5_curr(指標値)、最後から3番目のポイントma5_pre(指標値)、ma15指標データにも同じことが当てはまります。次に、図に示すように、これらのインジケーター データを使用してゴールデン クロスとデッド クロスを判断できます。 戦略を段階的に書く方法を教えます - 私の言語戦略を移植する このような状態が形成される限り、それはゴールデンクロスまたはデッドクロスであることが確定します。

信号判定部分は次のように記述できます。

if(_State == IDLE && ma5_pre < ma15_pre && ma5_curr > ma15_curr){     
    _State = OPENLONG
    Amount = 1
}  

if(_State == IDLE && ma5_pre > ma15_pre && ma5_curr < ma15_curr){     
    _State = OPENSHORT
    Amount = 1
}  

if(_State == LONG && ma5_pre > ma15_pre && ma5_curr < ma15_curr){     
    _State = COVERLONG
    Amount = 1
}  

if(_State == SHORT && ma5_pre < ma15_pre && ma5_curr > ma15_curr){     
    _State = COVERSHORT
    Amount = 1
}

これは移植が正常であることを意味し、戻ってテストすることができます。 JavaScript 戦略のバックテスト バックテスト構成: 戦略を段階的に書く方法を教えます - 私の言語戦略を移植する

回测结果:
![戦略を段階的に書く方法を教えます - 私の言語戦略を移植する](/upload/asset/16baa65d35e034e06a58.png) 

私の言語をバックテストする 戦略を段階的に書く方法を教えます - 私の言語戦略を移植する

バックテストの結果は基本的に同じであることがわかりますので、戦略にインタラクティブな機能を追加し続けたり、データ処理(Kライン合成など)を追加したり、カスタマイズされたチャートの描画と表示を追加したりしたい場合は、それ。

興味のある学生はぜひ試してみてください。