양적 세계로 데려다줍니다-- MACD 쌍방향 조작 슬라이드 스톱 손실 코드 분석

저자:작은 꿈, 2016-04-22 13:53:14, 업데이트: 2023-06-14 10:38:59

양적 세계로 데려다줍니다-- MACD 쌍방향 조작 슬라이드 스톱 손실 코드 분석

지난 기사에서 우리는 30줄의 코드에서 분량화를 위한 간소화 전략에 대해 알아봤습니다. 이 기사에서는 분량화를 시작하는 초보자들도 분량화 전략 설계의 즐거움을 조금 더 가까이 찾아갈 수 있도록 단계적으로 안내합니다. 이 문서는 계속, 이 경우에도 BTC의 현금 거래로 설명합니다. 저자는 금융, 투자, 증권 등에 대해 완전히 불완전합니다. 심지어 선물 거래 과정을 이해하지 못합니다. 또한 눈빛이 혼란스럽고, 낯선 이름이나 용어를 듣고, 머리가 흐트러지는 것, (그것이 실현되는 것도 조금 이해! 조금 이해!); 자신의 백두대간, 정보 확인 등을 통해 한 번 한 번 채워라. 관련 내용을 확인하고, 기본 개념을 가지고, 자신의 약간의 이해와 함께 간단한 JS 언어를 작성했습니다. 처음에는 K 라인, 평균 라인, MACD 지표가 무엇인지 몰랐습니다. 여기서 간단히 말해서, K선은 특정 주기의 시장 시장을 기록하여 시장 동력을 관찰하는 것이 좋습니다. 평균선은 이전 기사에서 사용 된 지표이며 MACD와 마찬가지로 시장 시장을 나타내는 지표입니다. 이 두 가지 지표의 개념, 알고리즘, 공식 추론 등이 모두 설명되어 있습니다. 이해가 안되는 경우 Baidu를 참조하십시오. (나는 Baidu에서보고 있습니다!)

코드는 다음과 같은 범용 변수를 가지고 있습니다. 오래된 규칙, 먼저 설명 한 번, 오래된 새는 무시할 수 있습니다.

변수 이름 초기 값 설명
간격 2000 이 변수는 라운치 사이클, 즉 프로그램이 일시 중지되는 대기 시간입니다. 단위는 밀리 초이고 1000 밀리 초는 1 초입니다. 따라서 이 변수의 초기 값은 2 초입니다.
STATE_FREE 0 이것은 상태 표시 변수이며, 빈자리를 나타냅니다. 상태 판단을 위해 사용됩니다.
STATE_BUY 1 이것은 상태 변수를 나타내는 것으로, 여러 개의 지분을 나타냅니다.
STATE_SELL 2 상태변수, 빈자두를 표시합니다.
ORDER_INVALID 3 보관 상태 변수는 보관되지 않은 것을 나타냅니다.
ORDER_VALID 4 그리고 그 다음에는
국가 STATE_FREE 상태변수, 빈 상태로 초기화.
신호 지연 0 원래 계획된 신호 지연, 일시적으로 쓸모없다.
stopProfit 0.002 이 변수는 더 중요하고, 중지 손실 비율, 예를 들어 자본 * 중지 손실 비율 ((0.002) 는 최대 손실의 0.002 배의 자본을 나타냅니다.
발걸음 0.5 슬라이드 스톱 손실의 단계 길이 값. 상승, 하락, 스톱 손실 가격의 차원.
op액 1 고정된 작업량.
이익 0

글로벌 객체, 보관 정보를 기록하는 데 사용되는, 몇 가지 방법을 포함, 주로 실현 슬라이드 스톱 손실.

    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;
	    }
	};
  • 기트허브에서 코드를 업로드합니다. 클릭하세요github
  • 공식 QQ 그룹에 가입하지 않은 사람은 가입하십시오: 309368835

이 함수들은 어떤 함수들이 사용되고 있는지

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;
}

아래는 정책의 메인 함수로 시작되며, 이 정책은 이전 30 줄의 직선 정책과 마찬가지로 거래 템플릿 클래스 라이브러리를 사용하여 거래 세부 사항을 포괄하고 있으며, 관심있는 친구들은 발명자 정량화에서 코드를 찾을 수 있으며, 공식 QQ 그룹 공유, 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);//轮询
    }
}

다음은 전략의 주요 부분, 오픈 플라시드 검사, 오픈 플라시드 작업이다.

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);//轮询间隔,就是让程序暂停一会儿。
    }
}

코드는 지쳤고, 물도 마시지 않았습니다.

먼저, 슬라이드 스톱의 원리에 대해 말씀드리겠습니다.

이 코드는 슬라이드 스톱에 관한 것입니다.SetStopPrice이 함수들은stopState그리고 그 다음에는ticker(시장 데이터) Stop Loss 가격을 업데이트합니다.stopState === STATE_BUY다른 상황에 따라 판단하고 정지값을 갱신합니다.orderState무효 상태 (즉, 유효한 포지션이 보유되지 않은 상태) 로 현재의 스톱 손실 가격을 반환한다. 만약 스톱 손실 가격이 0이라면, 그것을 매입 평균 가격으로 곱하여 초기화한다.(1 - stopProfit)◎ 다음으로, 최종 거래 가격에 따라 ◎ticker.Last그리고 보유가격this.price이 값은 현재 스톱손실 등급과 차이가 있습니다.this.level) 는 걸음의 곱셈과 비교된다. 만약 현재 순위를 초과한다면, 스리드 후값으로 정지 손실 가격을 업데이트하고, 동시에 정지 손실 순위를 증가시킨다. 그렇지 않으면 현재 정지 손실 가격을 그대로 유지한다.stopState === STATE_SELL), 논리는 비슷하지만, 마지막 거래 가격과 보유 가격의 차이에 대해 부정적인 값을 취하고, 중지 손실 가격을 업데이트 할 때 그 차이를 니다. 마지막으로, 업데이트 된 중지 손실 가격을 반환합니다.

슬라이드 스톱 손실은 위험 관리 전략입니다.

보유 과정에서 손실을 줄이거나 이익을 보호하기 위해 시장 가격의 변동에 따라 정지 가격을 조정합니다. 코드 논리에 따르면 슬라이드 정지 실현을위한 다음의 핵심 포인트를 볼 수 있습니다.updateCurrentProfit방법: 현재 수익/손실을 업데이트하여 보유 상태 (state) 와 최신 가격 (lastPrice) 에 따라 현재 수익/손실을 계산한다. 보유 상태가 빈 상태 (STATE_SELL) 이면 수익/손실은 최신 가격과 보유 가격의 차이에 의해 보유량으로 곱한다. 다중 상태 (STATE_BUY) 이면 수익/손실이 마이너스이다. SetStopPrice 방법은 중지/손실 가격을 업데이트하여 입력된 매개 변수 StopState (stopState) 와 최신 현상 가격 (ticker.Last) 에 따라 손실/손실 가격을 조정한다. 중지/손실 상태가 빈 상태 (STATE_FREE) 이면 현재 수익/손실 가격을 유지한다. 만약 보유 상태가 빈 상태 (STATE_BUY) 이면 손실/손실이 많으면 보유/손실 가격을 다른 상황에 따라 조정한다.1 - stopProfit이 경우, StopLoss가 1로 설정됩니다. 만약 마지막 거래 가격이 현재 차원보다 더 길다면 StopLoss가 슬라이드 이후의 StopLoss가로 설정되고 StopLoss가 상승합니다. 다른 경우 StopLoss가 변경되지 않습니다. 만약 StopLoss 상태가 STATE_SELL인 경우, 논리가 비슷합니다. initHoldOrder 방법은 평형 이후 보유 정보를 초기화하여 보유 상태, 평균 가격, 수, 운영 시간 StopLoss 가격 및 StopLoss 차원을 초기 상태로 다시 설정합니다.

모든 사람들이 먼저 다시 테스트를 실행 할 수 있습니다. 디지털 통화 거래 도서관 의 템플릿을 참조하는 것을 기억하십시오.

참고 자료


관련

더 많은

미드스키안녕하세요, 저는 www.banbiren.com에서 돈을 옮기는 사람이고, 거래 플랫폼을 옮기는 사람이고, 양적 거래를 배우고 있습니다. 제qq 번호:39866099입니다.

제로"이봐요, 이봐요, 이봐요.

무아정말 힘듭니다.

작은 꿈좋은 ^^, 당신은 바로 신청, MAC QQ는 초대 장소를 찾을 수 없습니다 >_<, 1 그룹 번호: 309368835 현재 몇 개의 위치가 있습니다.

작은 꿈젠장, 젠장

작은 꿈함께 공부하고요.