리소스 로딩... 로딩...

손잡이, 손잡이, 손잡이, 손잡이

저자:발명가들의 수량화 - 작은 꿈, 2019-10-21 14:59:12, 업데이트: 2023-10-17 21:22:56

img

손잡이, 손잡이, 손잡이, 손잡이

최근 친구와 전략에 대해 이야기하면서, My 언어 작성 전략의 사용에 대한 많은 유연성 문제가 있다는 것을 알게되었습니다. 많은 경우에 비 시스템으로 제공되는 표준 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)
    }
}

예를 들어, 이중평등 전략의 이식

어 리코드:img

메이 언어 전략 코드:

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

자바스크립트 정책으로 포트

먼저 재사용 가능한 예제 코드를 입력하여 시장 확보, 지표 계산을 입력합니다.

// 驱动策略的行情处理部分
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]

보시다시피, 이중 직선의 전략은 매우 간단합니다.records그리고 그것을 사용TA函数库이 함수들은TA.MA5일평균, 15일평균을 계산합니다. 다시 측정면에서는 K일평균이 일평균으로 설정되어 있습니다.TA.MA(records, 5)이 모든 것은 5일 평균으로 계산됩니다.TA.MA(records, 15)15일 평균선) ᅳ 그 다음으로ma5지표 데이터의 지수 두 번째 점ma5_curr(지표값) 세 번째 지점ma5_pre이 지표는ma15지표 데이터 대칭이다. 그 지표 데이터를 사용하여 금포를 판단할 수 있습니다.img이 상태가 형성되면 금포가 정해진 것이다.

이 신호를 판단하는 부분은 다음과 같이 쓸 수 있습니다.

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
}

이 경우, 이식은 괜찮습니다. 다시 테스트를 할 수 있습니다. 자바스크립트 정책 재검토 재검토 설정:img

回测结果:
![img](/upload/asset/16baa65d35e034e06a58.png) 

my 언어의 재검토img

재검토 결과는 기본적으로 동일하게 볼 수 있습니다. 만약 정책에 대한 상호 작용 기능을 계속 추가하고, 데이터 처리 (예를 들어 K선 합성) 를 추가하고, 사용자 정의 그래프 그래프 표시를 추가하고 싶다면 가능합니다.

흥미를 가진 학생은 직접 시도해 보세요.


관련

더 많은

소강배움