avatar of 发明者量化-小小梦 发明者量化-小小梦
konzentrieren Sie sich auf Private Nachricht
4
konzentrieren Sie sich auf
1271
Anhänger

Entführen Sie in die Welt der Quantifizierung ----- MACD-Zweiwegebetrieb, gleitender Stop-Loss-Code, Analyse

Erstellt in: 2016-04-22 13:53:14, aktualisiert am: 2023-06-14 10:38:59
comments   6
hits   7443

Entführen Sie in die Welt der Quantifizierung —– MACD-Zweiwegebetrieb, gleitender Stop-Loss-Code, Analyse

In diesem Artikel, in dem wir die Quantifizierungsstrategie für die vereinfachte 30 Zeilen Code im vorherigen Artikel erfahren haben, führt der Autor Schritt für Schritt die Quantifizierungs-Anfänger ein Stück näher an die Freude an der Entdeckung von Quantifizierungsstrategien. Der Autor ist ein völlig unerfahrener Fachmann in den Bereichen Finanzen, Investitionen, Wertpapiere und so weiter. Er versteht nicht einmal den Handelsprozess von Futures, aber er ist der Meinung, dass Bitcoin (BTC) eine sehr wichtige Währung ist. Es ist vielmehr ein verwirrter Verstand, der von unbekannten Begriffen und Begriffen betäubt ist. Nachdem ich die entsprechenden Inhalte durchgesehen hatte, hatte ich die grundlegenden Konzepte im Kopf und schrieb einfach eine in Verbindung mit der JS-Sprache, die ich ein wenig verstand. Zuerst wusste ich nicht, was K-Linie, Durchschnittslinie und MACD-Indikator waren. Die K-Linie ist ein Indikator, der die Marktentwicklung innerhalb eines bestimmten Zeitraums aufzeichnet. Die Gleichung ist ein Indikator, der wie der MACD-Indikator die Marktentwicklung widerspiegelt. Die Konzepte, Algorithmen, Formeln und so weiter sind in den beiden Indikatoren beschrieben.

Der Code enthält folgende globale Variablen, alte Regeln, erstes eine Interpretation, der Vogel kann ignoriert werden:

Variablen-Namen Anfangswert veranschaulichen
Interval 2000 Diese Variable ist die Umfragezeit, also die Zeit, die die Prozedur für die Wartepause benötigt. Die Einheit ist Millisekunden, 1000 Millisekunden sind 1 Sekunde, so dass der Anfangswert dieser Variable 2 Sekunden beträgt.
STATE_FREE 0 Dies ist eine Variable, die den Zustand bezeichnet und die Leere bezeichnet.
STATE_BUY 1 Dies ist eine Variable, die den Zustand einer Position mit mehreren Händlern angibt.
STATE_SELL 2 Statusvariable, die eine leere Position angibt.
ORDER_INVALID 3 Die Variable “Position gehalten” bedeutet “nicht gehalten”.
ORDER_VALID 4 Das ist eine sehr schwierige Aufgabe.
state STATE_FREE Statusvariablen, die mit null initialisiert werden.
SignalDelay 0 Die ursprünglich geplante Signalverzögerung ist vorläufig unbrauchbar.
stopProfit 0.002 Die Stop-Loss-Variable ist wichtig, z. B. Kapital * Stop-Loss-Variable ((0,002)) bedeutet maximal 0,002 mal Kapital und maximal Verlust.
step 0.5 Die Schrittlänge des Schiebe-Stopp-Wertes. Der Grad, der verwendet wird, um den Stop-Loss-Preis zu erhöhen oder zu senken.
opAmount 1 Festgelegter Betrieb.
profit 0 Verlust.

Globale Objekte, die zur Erfassung von Positionsinformationen verwendet werden, enthalten einige Methoden, die hauptsächlich zum Erreichen von Rutschstopps dienen.

    var holdOrder = {//持仓信息对象
	    orderState: ORDER_INVALID,// 持仓状态
	    price: 0, //持仓均价
	    amount: 0, //持仓量
	    time: null, // 操作时间
	    stopPrice: 0, // 止损价
	    level: 1,   //止损等级
	    updateCurrentProfit: function(lastPrice,amount){//更新当前盈亏
	        if(state === STATE_SELL){//当前 空头持仓
	        	return (lastPrice - this.price) * amount;
	        }
	        if(state === STATE_BUY){//当前 多头持仓
	        	return - (lastPrice - this.price) * amount;
	        }
	    },
	    SetStopPrice: function(ticker,stopState){//更新止损价
	    	if(stopState === STATE_FREE){ //更新止损时状态 为空闲
	    		return this.stopPrice;
	    	}
	    	if(stopState === STATE_BUY){ //更新止损时状态 为多仓
	            if(this.orderState === ORDER_INVALID){
	        	    return this.stopPrice;
	            }
	            if(this.stopPrice === 0){//初始 止损价为0 时 
	            	this.stopPrice = this.price * ( 1 - stopProfit );
	            }
	            if( ticker.Last <= this.price ){ //最后成交价 小于等于  持仓均价时
	                this.stopPrice = this.price * ( 1 - stopProfit );
	                this.level = 1;
	            }else{//其它情况
	        	    if( ticker.Last - this.price > this.level * step ){//超出当前等级   设置滑动止损
	                    this.stopPrice = this.price * (1 - stopProfit) + (ticker.Last - this.price );
	                    //更新止损价为滑动后的止损价
	                    this.level++;//上调止损等级
	        	    }else{//其它
	        	    	this.stopPrice = this.stopPrice;//保持当前止损价不变
	        	    }
	            }
	    	}else if( stopState === STATE_SELL){//空头持仓类似
	    		if(this.orderState === ORDER_INVALID){
	        	    return this.stopPrice;
	            }
	            if(this.stopPrice === 0){
	            	this.stopPrice = this.price * ( 1 + stopProfit );
	            }
	            if( ticker.Last >= this.price ){
	                this.stopPrice = this.price * ( 1 + stopProfit );
	                this.level = 1; 
	            }else{
	        	    if( this.price - ticker.Last > this.level * step ){
	                    this.stopPrice = this.price * (1 + stopProfit) - ( this.price - ticker.Last );
	                    this.level++;
	        	    }else{
	        	    	this.stopPrice = this.stopPrice;
	        	    }
	            }
	    	}
	        return this.stopPrice;//返回止损价
	    },
	    initHoldOrder: function(){//平仓后  用于 初始化持仓信息的  函数
	        this.orderState = ORDER_INVALID;
	        this.price = 0;
	        this.amount = 0;
	        this.time = null;
	        this.stopPrice = 0;
	        this.level = 1;
	    }
	};
    
  • Der Code wurde auf GitHub hochgeladen. KlickengithubEintritt

  • Wer nicht Mitglied einer offiziellen QQ-Gruppe ist, kann sich an der 309368835 Inventor Quantity Exchange Gruppe beteiligen.


Hier ist eine kurze Vorschau der Funktionen, die wir verwenden werden.

function MACD_Cross(){//检测MACD指标,交叉状态的函数
    var records = exchange.GetRecords();//获取K线数据
    while(!records || records.length < 45){ //K线数据不能为null,要大于45个柱,不符合标准 循环获取直到符合
    	records = exchange.GetRecords();
    	Sleep(Interval);
    }
    var macd = TA.MACD(records,12,26,9);//调用指标函数, 参数为MACD 默认的参数。
    var dif = macd[0];  //dif线
    var dea = macd[1];  //dea线
    var column = macd[2]; // MACD柱
    var len = records.length;  //K线周期长度
    if( (dif[len-1] > 0 && dea[len-1] > 0) && dif[len-1] > dea[len-1] && dif[len-2] < dea[len-2] && column[len-1] > 0.2 ){ 
    //判断金叉条件:dif 与 dea 此刻均大于0 , 且dif由下上穿dea , 且 MACD量柱大于0.2
    	return 1; //返回1  代表 金叉信号。
    }
    if( (dif[len-1] < 0 && dea[len-1] < 0) && dif[len-1] < dea[len-1] && dif[len-2] > dea[len-2] && column[len-1] < -0.2 ){
    //判断死叉条件:
        return 2;//返回2  代表 死叉信号。
    }   
    return 0;  //金叉  、死叉  信号以外,为等待信号 0 。
}
function getTimeByNormal(time){// 获取时间的 函数 把毫秒时间 转换 标准时间
    var timeByNormal = new Date();
    timeByNormal.setTime(time);
    var strTime = timeByNormal.toString();
    var showTimeArr = strTime.split(" ");
    var showTime = showTimeArr[3]+"-"+showTimeArr[1]+"-"+showTimeArr[2]+"-"+showTimeArr[4];
    return showTime;
}

Im Folgenden geht es in die Hauptfunktion der Strategie ein, die wie die vorherige 30-Zeilen-Gleichlinien-Strategie eine Bibliothek von Handelsschablonen verwendet, die die Einzelheiten der Transaktionsunterlagen enthält. Interessierte Freunde können den Code auf Quantify the Inventor finden, die kommentierte Version wird in der offiziellen QQ-Gruppe geteilt und auf github.

function main(){
    var initAccount = $.GetAccount(exchange);//首先我们来记录初始时的账户信息,这里调用了模板类库的导出函数
    var nowAccount = initAccount;//再声明一个 变量 表示 现在账户信息
    var diffMoney = 0; //钱 差额
    var diffStocks = 0;//币 差额
    var repair = 0; //计算 盈亏时   用于修正的 量
    var ticker = exchange.GetTicker(); //获取此刻市场行情
    Log("初始账户:",initAccount); //输出显示  初始账户信息。
    while(true){//主函数循环
        scan(); //扫描函数,  稍后讲解,主要是判断  开仓、平仓 以及 操作 开仓 、 平仓。
        ticker = exchange.GetTicker();//在while循环内 获取 市场行情
        if(!ticker){//如果 没有获取到  (null) 跳过以下 重新循环
        	continue;
        }
        if(holdOrder.orderState == ORDER_VALID){//判断当前是否  持仓
        	Log("当前持仓:",holdOrder); //如果 当前持仓   输出  持仓 信息
        }
        if(holdOrder.orderState == ORDER_INVALID){//如果 未持仓(已平仓)
        	nowAccount = $.GetAccount(exchange); //获取当前账户信息
            diffMoney = nowAccount.Balance - initAccount.Balance; //计算  当前账户  与 初始账户之间的  钱 差额
            diffStocks = nowAccount.Stocks - initAccount.Stocks; // 计算  当前账户  与  初始账户之间的  币 差额
            repair = diffStocks * ticker.Last; //把 币的差额 * 最后成交价  ,转为等值的钱, 用于计算 盈亏
            LogProfit(diffMoney + repair ,"RMB","现在账户:",nowAccount,"本次盈亏:",profit);//输出 盈亏 信息
        }
    	Sleep(Interval);//轮询
    }
}

Im Anschluss folgen die Hauptteile der Strategie, die Eröffnung von Lagerstätten, die Ermittlung von Lagerstätten und die Eröffnung von Lagerstätten.

function scan(){
	var sellInfo = null; //声明  储存平仓信息的变量  , 初始化null
	var buyInfo = null;  //声明  开仓的 , 初始化null
	var opFun = null;//  开仓函数, 两种状态 ,  开多仓 ,  开空仓。
	var singal = 0; //信号
    while(true){//检测 及操作 循环
        var ticker = exchange.GetTicker(); //获取市场行情
        if(!ticker){ //判断 获取失败  跳过以下 ,继续循环获取
        	continue;
        }
        holdOrder.SetStopPrice(ticker,state); //设置 持仓 止损价
        if(state === STATE_FREE &&  (singal = MACD_Cross()) !== 0  ){
        	//判断策略运行状态是否空闲、此刻MACD指标信号是否空闲, 符合 策略运行状态空闲 且 有金叉或死叉执行以下
        	holdOrder.initHoldOrder();//初始化持仓信息
            opFun = singal === 1 ?  $.Buy : $.Sell ;//根据MACD_Cross函数返回结果,判断开多仓、开空仓。
            buyInfo = opFun(opAmount);//开仓操作
            holdOrder.orderState = ORDER_VALID;//设置持仓信息,状态为持仓
            holdOrder.price = buyInfo.price; //设置持仓均价  由 开仓操作函数 opFun返回。 
            holdOrder.amount = buyInfo.amount; //设置持仓量
            holdOrder.time = getTimeByNormal((new Date()).getTime());//设置持仓开始的时间
            state = singal === 1 ? STATE_BUY : STATE_SELL; //更新策略状态为多仓 或 空仓
            var account = $.GetAccount(exchange); //获取账户信息
            if(singal === 1){//输出开仓方向 和 当前账户信息
            	Log("开多仓。","账户:",account);
            }else{
                Log("开空仓。","账户:",account);
            }
            break;
        }else{
        	var lastPrice = holdOrder.price;// 把持仓均价 赋值 给 lastPrice
        	if( state === STATE_BUY && holdOrder.orderState === ORDER_VALID && ticker.Last < holdOrder.stopPrice ){
            //如果 多仓 且 持仓信息为持仓 且 最后成交价 小于止损价,执行以下
        	    Log("多头止损平仓","初始止损价:",holdOrder.price * (1 - stopProfit),"--滑动止损价:",holdOrder.stopPrice,"最后成交价:",ticker.Last,"止损等级:",holdOrder.level);//多头止损平仓信息
        	    sellInfo = $.Sell(holdOrder.amount);//平仓
                holdOrder.orderState = ORDER_INVALID;//平仓信息 更新进对象
                holdOrder.price = sellInfo.price;
                holdOrder.amount = sellInfo.amount;
                holdOrder.time = getTimeByNormal((new Date()).getTime());
                profit = holdOrder.updateCurrentProfit(lastPrice,sellInfo.amount);//更新浮动盈亏
        	    state = STATE_FREE;//更新状态
        	    break;//跳出
        	}
        	if( state === STATE_SELL && holdOrder.orderState === ORDER_VALID && ticker.Last > holdOrder.stopPrice ){//同上 , 这个是空头止损平仓
        	    Log("空头止损平仓","初始止损价:",holdOrder.price * (1 + stopProfit),"--滑动止损价:",holdOrder.stopPrice,"最后成交价:",ticker.Last,"止损等级:",holdOrder.level);//测试
        	    sellInfo = $.Buy(holdOrder.amount);
                holdOrder.orderState = ORDER_INVALID;
                holdOrder.price = sellInfo.price;
                holdOrder.amount = sellInfo.amount;
                holdOrder.time = getTimeByNormal((new Date()).getTime());
                profit = holdOrder.updateCurrentProfit(lastPrice,sellInfo.amount);
        	    state = STATE_FREE;
        	    break;
        	}
            if(state === STATE_BUY && MACD_Cross() === 2 ){//做多时,MACD指标死叉 -- 死叉平仓
        	    sellInfo = $.Sell(holdOrder.amount);
        	    Log("死叉平仓","初始止损价:",holdOrder.price * (1 - stopProfit),"--滑动止损价:",holdOrder.stopPrice,"最后成交价:",ticker.Last,"止损等级:",holdOrder.level);//测试
                holdOrder.orderState = ORDER_INVALID;
                holdOrder.price = sellInfo.price;
                holdOrder.amount = sellInfo.amount;
                holdOrder.time = getTimeByNormal((new Date()).getTime());
                profit = holdOrder.updateCurrentProfit(lastPrice,sellInfo.amount);
        	    state = STATE_FREE;
        	    break;
            }
             if(state === STATE_SELL && MACD_Cross() === 1 ){//做空时,MACD指标金叉 ---金叉平仓
        	    sellInfo = $.Buy(holdOrder.amount);
        	    Log("金叉平仓","初始止损价:",holdOrder.price * (1 + stopProfit),"--滑动止损价:",holdOrder.stopPrice,"最后成交价:",ticker.Last,"止损等级:",holdOrder.level);//测试
                holdOrder.orderState = ORDER_INVALID;
                holdOrder.price = sellInfo.price;
                holdOrder.amount = sellInfo.amount;
                holdOrder.time = getTimeByNormal((new Date()).getTime());
                profit = holdOrder.updateCurrentProfit(lastPrice,sellInfo.amount);
        	    state = STATE_FREE;
        	    break;
            }
        }
        Sleep(Interval);//轮询间隔,就是让程序暂停一会儿。
    }
}

Ich habe genug von dem Code, ich habe genug von dem Trinken.

Zunächst einmal über die Grundsätze der Rutschstopps.

In diesem Abschnitt über die Rutsch-Stopp-Kode ist zu lesen:SetStopPriceDie Funktion basiert auf dem EingangstopState(Stillstand) undticker(Marktdaten) um den Stop-Loss-Preis zu aktualisieren.stopState === STATE_BUYWenn der Stop-Loss-Preis von einem Unternehmen in einem anderen Land oder in einem anderen Land ermittelt wird, wird der Stop-Loss-Preis in diesem Land oder in einem anderen Land verändert.orderStateAls ungültig ((d. h. keine gültige Position gehalten), wird der aktuelle Stop-Loss-Preis zurückgegeben. Wenn der Stop-Loss-Preis 0 ist, wird er mit dem Kauf-Mittelpreis multipliziert.(1 - stopProfit)│ │ │ │ │ticker.Last) und der durchschnittliche Kurs der Positionen (this.price) gegenüber dem aktuellen Stop-Loss-Level)this.level) mit der Multiplikation der Schrittlänge (step) verglichen werden. Wenn die aktuelle Stufe überschritten wird, wird der Stop-Loss-Wert als der Wert nach der Rutsche aktualisiert, während die Stop-Loss-Stufe erhöht wird. Ansonsten bleibt der aktuelle Stop-Loss-Wert unverändert.stopState === STATE_SELLDie Logik ist ähnlich, aber die Differenz zwischen dem Endpreis und dem Kurswert wird negativ und bei der Aktualisierung des Stop-Loss-Preises wird die Differenz abgezogen. Schließlich wird der Stop-Loss-Preis zurückgegeben.

Der Slip Stop ist eine Risikomanagement-Strategie.

Während der Positionshaltung wird der Stop-Loss-Preis entsprechend der Marktpreisfluktuation angepasst, um Verluste zu verringern oder Gewinne zu schützen. Nach der Logik des Codes lassen sich die folgenden Schlüsselpunkte erkennen, um einen Slippestop zu erreichen:updateCurrentProfitDie Methode SetStopPrice wird verwendet, um den aktuellen Stop-Loss-Preis zu aktualisieren. Der Stop-Loss-Preis wird anhand der eingegebenen Parameter stopState (Stop-Loss-State) und der aktuellen Kursticker (Last-Last) angepasst. Wenn der Stop-Loss-State leer ist, bleibt der aktuelle Stop-Loss-Preis unverändert.1 - stopProfitWenn der Stop-Loss-Status null ist (STATE_SELL), ist die Logik ähnlich. Die initHoldOrder-Methode wird verwendet, um die Positionsinformationen nach dem Platzieren zu initialisieren und den Positionsstatus, den Durchschnitt, die Menge, den Betriebszeit, den Stop-Preis und den Stop-Loss-Status in den Anfangszustand zurückzusetzen.

Wenn Sie sich mit dem Thema beschäftigen möchten, dann können Sie zuerst einen Test durchführen, aber denken Sie daran, sich an die Vorlage zu beziehen, die Sie hier finden können.

Verweise