Đưa bạn vào thế giới định lượng -- MACD hai chiều điều hành trượt dừng mất tích mã phân tích

Tác giả:Giấc mơ nhỏ, Tạo: 2016-04-22 13:53:14, Cập nhật: 2023-06-14 10:38:59

Đưa bạn vào thế giới định lượng -- MACD hai chiều điều hành trượt dừng mất tích mã phân tích

Trong bài viết trước, chúng ta đã tìm hiểu về các chiến lược định lượng đơn giản trong 30 dòng mã, và trong bài viết này, tác giả sẽ đưa người mới bắt đầu định lượng từng bước để khám phá thêm niềm vui của việc thiết kế chiến lược định lượng. Trong khi đó, các nhà đầu tư cũng không hiểu gì về các giao dịch tương lai, và các nhà đầu tư cũng không hiểu gì về các giao dịch tương lai. Những người bị mê hoặc bởi những điều mà họ không biết, những cái tên và thuật ngữ mà họ chưa từng nghe thấy, và những người bị mê hoặc bởi những điều mà họ đã làm, (những điều mà họ đã thực hiện cũng hiểu một chút! hiểu một chút!); bằng cách tìm kiếm thông tin của mình. Sau khi xem nội dung liên quan, tôi đã có những khái niệm cơ bản trong tâm trí, kết hợp với ngôn ngữ JS mà tôi hiểu một chút, tôi đã viết một bài viết đơn giản. Ban đầu tôi không hiểu gì về đường K, đường trung bình, chỉ số MACD. Nói một cách đơn giản, đường K là đường ghi lại thị trường trong một chu kỳ nhất định, giúp quan sát được động lực của thị trường. Đường trung bình là chỉ số được sử dụng trong bài viết trước đây và cũng giống như chỉ số MACD, là chỉ số phản ánh xu hướng thị trường. Các khái niệm, thuật toán, công thức dẫn xuất và các chỉ số khác nhau đã được mô tả. Nếu không hiểu, hãy truy cập Baidu.

Có những biến thể toàn cầu sau đây trong mã, những quy tắc cũ, giải thích từng thứ một trước khi, những con chim cũ có thể bỏ qua.

Tên biến Giá trị ban đầu Giải thích
Khoảng thời gian 2000 Các biến số này là chu kỳ vòng quay, hoặc thời gian mà chương trình tạm dừng chờ đợi, đơn vị là millisecond, 1000 millisecond là 1 giây, vì vậy giá trị ban đầu của biến số này là 2 giây.
STATE_FREE 0 Đây là một biến thể thể hiện trạng thái, biểu thị khoảng trống.
STATE_BUY 1 Đây là một biến thể biểu thị trạng thái, biểu thị nhiều đầu tư.
STATE_SELL 2 Các biến trạng thái, cho thấy giữ trống.
ORDER_INVALID 3 Các biến trạng thái lưu trữ, cho thấy không lưu trữ.
ORDER_VALID 4 Có nghĩa là chúng tôi đang giữ...
nhà nước STATE_FREE Các biến trạng thái được khởi tạo bằng trạng thái trống.
Tín hiệuDelay 0 Ban đầu dự kiến, tín hiệu bị chậm, tạm thời không hiệu quả.
StopProfit 0.002 Một biến số quan trọng hơn, tỷ lệ dừng lỗ, ví dụ như vốn * tỷ lệ dừng lỗ ((0.002) cho thấy mức thua lỗ tối đa là 0.002 lần vốn, mức thua lỗ tối đa.
bước 0.5 Giá trị bước dừng trượt; được sử dụng để nâng, hạ giá dừng trượt;
opTổng 1 Số lượng hoạt động cố định.
Lợi nhuận 0 Những người dân ở đây rất tiếc.

Đối tượng toàn cầu, được sử dụng để ghi lại thông tin lưu trữ, chứa một số phương pháp, chủ yếu là thực hiện dừng trượt.

    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;
	    }
	};
  • Có thể bạn có thể tải lên mã từ địa chỉ Github: Nhấp vàogithubNhìn vào đây nhé.
  • Nếu bạn chưa tham gia vào nhóm QQ chính thức, hãy tham gia: 309368835

Dưới đây chúng ta sẽ xem xét nhanh các hàm sẽ được sử dụng.

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

Dưới đây bắt đầu vào các chức năng chính của chính sách, chính sách này sử dụng thư viện các mẫu giao dịch như chính sách đường thẳng 30 dòng trước đây, bao gồm chi tiết giao dịch, bạn bè quan tâm có thể tìm thấy mã trên các nhà phát minh định lượng, phiên bản chú thích được chia sẻ trên nhóm QQ chính thức, 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);//轮询
    }
}

Tiếp theo là phần chính của chiến lược, kiểm tra giao dịch mở và giao dịch mở.

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

Cóc mệt mỏi, ngưng uống nước

Trước tiên, hãy nói về nguyên tắc dừng trượt.

Trong đoạn mã này về việc dừng trượt, bạn có thể tìm thấy một số thông tin về việc dừng trượt.SetStopPriceChức năng dựa trên thông tin truyền vàostopState(đã dừng) vàticker(Dữ liệu thị trường) để cập nhật giá dừng lỗ.stopState === STATE_BUY), để đánh giá và cập nhật giá dừng lỗ theo các trường hợp khác nhau; nếuorderStateTrở lại giá dừng lỗ hiện tại nếu giá dừng lỗ là 0, khởi tạo bằng giá mua trung bình nhân:(1 - stopProfit)Sau đó, dựa trên giá giao dịch cuối cùng.ticker.Last) và giữ giá tương đương)))this.priceCác giá trị khác nhau của các loại thuốc này là:this.level) được so sánh với số lần bước. Nếu vượt quá mức hiện tại, giá dừng lỗ được cập nhật thành giá sau khi trượt, đồng thời tăng mức dừng lỗ; nếu không, giữ giá dừng lỗ hiện tại không thay đổi. Đối với giữ trống.stopState === STATE_SELLCác giá trị giao dịch cuối cùng được tính bằng giá cổ phần và giảm giá trị này khi cập nhật giá dừng. Cuối cùng, trả lại giá dừng sau khi cập nhật.

Đánh lỗ trượt là một chiến lược quản lý rủi ro

Trong quá trình nắm giữ, giá dừng lỗ được điều chỉnh theo sự biến động của giá thị trường để giảm lỗ hoặc bảo vệ lợi nhuận. Theo logic của mã, các điểm then chốt sau đây có thể được nhìn thấy để đạt được dừng trượt:updateCurrentProfitPhương pháp được sử dụng để cập nhật lỗ/lợi hiện tại, tính toán lỗ/lợi hiện tại dựa trên trạng thái nắm giữ (state) và giá cuối cùng (lastPrice). Nếu nắm giữ là trạng thái bán trống (STATE_SELL), thì lỗ/lợi là chênh lệch giữa giá gần nhất và giá giữ bằng gấp đôi số lượng nắm giữ; nếu là trạng thái nhiều đầu (STATE_BUY), thì lỗ/lợi là âm. Phương pháp SetStopPrice được sử dụng để cập nhật giá dừng lỗ (stopPrice). Tùy theo các tham số được truyền vào (stopState) và giá giữ gần nhất (ticker.Last), điều chỉnh giá dừng lỗ (stop loss). Nếu trạng thái dừng lỗ trống (STATE_FREE), giữ giá dừng lỗ hiện tại không thay đổi.1 - stopProfitNếu giá giao dịch cuối cùng vượt quá bước (step), giá dừng được thiết lập là giá dừng sau khi trượt, và mức dừng được nâng lên. Trong trường hợp khác, giá dừng không thay đổi. Nếu trạng thái dừng là STATE_SELL, logic tương tự.

Bạn có thể chạy lại thử nghiệm trước, hãy nhớ tham khảo mẫu của thư viện giao dịch tiền kỹ thuật số.

Tài liệu tham khảo


Có liên quan

Thêm nữa

MidskyXin chào chủ nhà, tôi là www.banbiren.com, người chuyển tiền, người viết về sàn giao dịch chuyển tiền, đang học cách giao dịch định lượng, tôi là: 39866099, có thể mời tôi tham gia nhóm này không?

KhôngTăng trưởng rất nhanh.

muiaThật khó khăn.

Giấc mơ nhỏĐược rồi ^^, bạn ở bên này. Đơn trực tiếp, MAC QQ không tìm thấy địa điểm mời >_<, 1 số nhóm: 309368835 Bây giờ có một số vị trí.

Giấc mơ nhỏỒ, ừ, ừ.

Giấc mơ nhỏHãy cùng nhau học.