avatar of 发明者量化-小小梦 发明者量化-小小梦
fokus pada mesej peribadi
4
fokus pada
1271
Pengikut

Membawa anda ke dalam dunia kuantifikasi - analisis kod henti rugi gelongsor operasi dua hala MACD

Dicipta dalam: 2016-04-22 13:53:14, dikemas kini pada: 2023-06-14 10:38:59
comments   6
hits   7443

Membawa anda ke dalam dunia kuantifikasi - analisis kod henti rugi gelongsor operasi dua hala MACD

Kami telah membincangkan strategi kuantiti 30 baris dalam artikel sebelum ini, dan dalam artikel ini kami akan membawa anda lebih dekat dengan reka bentuk strategi kuantiti. Sebelum ini, penulis tidak begitu mahir dalam bidang kewangan, pelaburan, sekuriti, dan lain-lain. Lebih-lebih lagi, mereka yang terganggu dengan mata mereka, mendengar nama-nama dan istilah-istilah yang tidak diketahui, dan mereka yang tertekan dengan fikiran mereka. Setelah membaca kandungan yang berkaitan, dengan konsep asas dalam fikiran, dengan bahasa JS yang saya sedikit faham, saya hanya menulis satu. Pada mulanya saya tidak faham apa itu garis K, garis rata-rata, dan penunjuk MACD. Di sini secara ringkas, garis K adalah merekodkan pergerakan pasaran dalam tempoh tertentu, memudahkan untuk melihat dinamik pasaran. Garis rata adalah penunjuk yang digunakan dalam artikel sebelumnya, seperti penunjuk MACD, adalah penunjuk yang mencerminkan trend pergerakan pasaran. Konsep-konsep, algoritma, formula-rumus, dan lain-lain mengenai kedua-dua penunjuk ini telah dibincangkan. Bagi yang tidak faham, sila lihat peratusan.

Kod ini mengandungi pembolehubah global, peraturan lama, tafsiran pertama, burung tua boleh diabaikan.

Nama pemboleh ubah Nilai permulaan menggambarkan
Interval 2000 Variabel ini adalah kitaran tinjauan pendapat, iaitu jumlah masa yang dihabiskan untuk program menunggu sementara, dan unitnya adalah milidetik, 1000 milidetik adalah 1 saat, jadi nilai awal untuk variabel ini adalah 2 saat.
STATE_FREE 0 Ini adalah pembolehubah yang menunjukkan keadaan, yang menunjukkan kosong. Ia digunakan untuk menilai keadaan.
STATE_BUY 1 Ini adalah pembolehubah keadaan yang menunjukkan bahawa anda memegang banyak kedudukan.
STATE_SELL 2 Variable status, menunjukkan kedudukan kosong.
ORDER_INVALID 3 Variabel status memegang, yang menunjukkan tidak memegang kedudukan.
ORDER_VALID 4 Ia menunjukkan bahawa…
state STATE_FREE Peubah keadaan, inisialisasi dengan keadaan kosong.
SignalDelay 0 Sinyal yang dijangkakan terlewat, sementara tidak berfungsi.
stopProfit 0.002 Variabel ini lebih penting, kadar hentian, contohnya wang tunai * kadar hentian ((0.002) menunjukkan maksimum kerugian sebanyak 0.002 kali wang tunai, had kerugian maksimum.
step 0.5 Panjang langkah peluru berpindah. Digunakan untuk menaikkan atau menurunkan paras peluru berpindah.
opAmount 1 Jumlah operasi tetap.
profit 0 Kerugian.

Objek global, yang digunakan untuk mencatat maklumat pegangan, mengandungi beberapa kaedah, terutamanya untuk mencapai Stop Loss Sliding.

    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;
	    }
	};
    
  • Kode ini dimuat naik di github: klikgithubMasuk

  • Jika anda tidak menyertai kumpulan QQ rasmi, sila sertai: 309368835 Inventor Quantitative Exchange Group.


Di bawah ini, kita akan melihat secara ringkas fungsi yang akan kita gunakan.

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

Berikut adalah fungsi utama strategi, yang menggunakan perpustakaan templat perdagangan yang dibungkus dengan butiran pesanan perdagangan, dan rakan yang berminat boleh mencari kodnya di inventori kuantitatif, dan versi komentarnya di kongsi di kumpulan QQ rasmi, 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);//轮询
    }
}

Berikut adalah bahagian utama strategi, pengesanan simpanan simpanan, dan operasi simpanan simpanan simpanan.

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

“Saya tidak tahu apa-apa, saya tidak tahu apa-apa, saya tidak tahu apa-apa.

Pertama, kita akan bercakap tentang prinsip-prinsip penghentian glising.

Dalam kod ini, yang berkaitan dengan penghentian glising,SetStopPriceFungsi berdasarkan inputstopState(Keadaan terhenti) danticker(Data pasaran) untuk mengemas kini harga hentian kerugian.stopState === STATE_BUY), menilai dan mengemas kini harga berhenti kerugian mengikut keadaan yang berbeza.orderStateUntuk keadaan tidak sah ((iaitu tidak memegang kedudukan yang sah), kembalikan harga berhenti sekarang. Jika harga berhenti adalah 0, maka mulakan dengan harga purata beli kali(1 - stopProfit)Kemudian, berdasarkan harga akhir transaksi,ticker.Last) dan harga purata peganganthis.price) berbanding dengan tahap stop loss semasa)this.level) dengan kelipatan langkah panjang ((step)). Jika melebihi tahap semasa, kemas kini harga hentian sebagai nilai selepas meluncur, sambil meningkatkan tahap hentian; jika tidak, mengekalkan harga hentian semasa tidak berubah.stopState === STATE_SELL), logikanya sama, tetapi mengambil nilai negatif dari perbezaan antara harga dagangan terakhir dan harga purata pegangan, dan mengurangkan perbezaan itu semasa mengemas kini harga hentian. Akhirnya, kembali kepada harga hentian yang diperbaharui.

Stop loss adalah strategi pengurusan risiko.

Semasa memegang kedudukan, anda harus menyesuaikan harga hentian anda dengan turun naik harga pasaran untuk mengurangkan kerugian atau melindungi keuntungan. Berdasarkan logik kod, anda dapat melihat titik-titik penting berikut untuk mencapai hentian tergelincir:updateCurrentProfitKaedah digunakan untuk mengemas kini keuntungan dan kerugian semasa, berdasarkan keadaan memegang jawatan ((state) dan harga terkini ((lastPrice)). Jika memegang jawatan adalah keadaan menjual kosong ((STATE_SELL), kerugian adalah perbezaan harga terkini dengan harga purata memegang jawatan berganda dengan jumlah kedudukan memegang jawatan; jika keadaan bertolak ansur ((STATE_BUY), kerugian adalah negatif. Kaedah SetStopPrice digunakan untuk mengemas kini harga henti kerugian. Berdasarkan parameter yang dihantar stopState (((stop loss status) dan harga terkini berjalan ticker (((.Last), sesuaikan harga henti kerugian.1 - stopProfit), dan menetapkan semula paras penutupan kepada 1. ❚ Jika harga transaksi terakhir melebihi langkah peringkat semasa ((step), harga penutupan akan ditetapkan sebagai harga penutupan selepas tergelincir, dan tahap penutupan akan dinaikkan. ❚ Dalam kes lain, harga penutupan akan kekal sama.

Anda boleh menjalankan percubaan semula, dan ingat untuk merujuk kepada templat ini!

Rujukan