Membawa Anda ke dalam dunia kuantitatif -- MACD dua arah operasi slider stop loss kode analisis

Penulis:Mimpi kecil, Dibuat: 2016-04-22 13:53:14, Diperbarui: 2023-06-14 10:38:59

Membawa Anda ke dalam dunia kuantitatif -- MACD dua arah operasi slider stop loss kode analisis

Dalam artikel sebelumnya, kami telah mempelajari strategi kuantitatif sederhana untuk kode 30 baris, dan di artikel ini, penulis akan mengambil langkah demi langkah untuk membawa pemula kuantitatif lebih dekat untuk mengeksplorasi kesenangan merancang strategi kuantitatif. Dalam artikel ini, penulis melanjutkan, "Ini adalah perdagangan langsung dengan BTC, yang sebelumnya tidak memiliki pengetahuan tentang keuangan, investasi, sekuritas, dll. Bahkan, orang-orang yang bingung dengan mata mereka, mendengar kata-kata atau istilah yang belum pernah mereka dengar, dan bingung dengan pikiran mereka, (yang dimengerti sedikit! sedikit mengerti!) Setelah membaca konten yang terkait, saya memiliki konsep dasar, dan menggabungkan bahasa JS yang saya pahami sedikit, saya menulis sederhana. Awalnya saya tidak tahu apa itu K-line, rata-rata, indikator MACD. Secara sederhana, garis K adalah garis yang mencatat pasar selama periode tertentu, yang memungkinkan Anda untuk melihat dinamika pasar. Garis rata-rata adalah indikator yang digunakan dalam artikel sebelumnya, dan seperti indikator MACD, merupakan indikator yang mencerminkan tren pasar. Konsep, algoritma, dan formula inferensi dari kedua indikator ini sudah dijelaskan secara bergantian.

Ada beberapa variabel global di dalam kode, aturan lama, penjelasan pertama, burung tua bisa diabaikan.

Nama variabel Nilai awal Penjelasan
Interval 2000 Variabel ini adalah siklus rundingan, yaitu jumlah waktu yang dibutuhkan untuk program berhenti menunggu, satuan adalah milidetik, 1000 milidetik adalah 1 detik, jadi variabel ini memiliki nilai awal 2 detik.
STATE_FREE 0 Ini adalah variabel yang menunjukkan status, yang menunjukkan ruang kosong.
STATE_BUY 1 Ini adalah variabel yang menunjukkan status, yang berarti multi-headed holdings.
STATE_SELL 2 Variabel status, yang menunjukkan posisi kosong.
ORDER_INVALID 3 Variabel status penyimpanan, menunjukkan tidak ada penyimpanan.
ORDER_VALID 4 Ini menunjukkan bahwa dalam penyimpanan...
negara bagian STATE_FREE Variabel status, diinisialisasi dengan status kosong.
SinyalTunda 0 Pada awalnya direncanakan, sinyal tertunda, sementara tidak berguna.
StopProfit 0.002 Variabel ini lebih penting, stop loss rate, misalnya modal * stop loss rate ((0.002) menunjukkan kerugian maksimum 0.002 kali modal, kerugian atas.
langkah 0.5 Slide stop loss step length value. Untuk naik, turun, dan tingkat harga stop loss.
OpJumlah 1 Perangkat lunak ini dapat digunakan untuk membuat aplikasi.
keuntungan 0 Saya tidak tahu apa yang terjadi.

Objek global, digunakan untuk mencatat informasi penyimpanan, berisi beberapa metode, terutama untuk mencapai stop loss geser.

    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;
	    }
	};
  • Di sini Anda dapat mengunggah kode ke alamat github: KlikgithubMasuklah.
  • Jika Anda belum bergabung dengan grup QQ resmi di sini, silakan bergabung: 309368835 Penemu Kuantitatif Grup Pertukaran.

Di bawah ini kita akan melihat secara singkat fungsi yang akan digunakan.

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

Di bawah ini, mulailah dengan fungsi utama dari strategi, yang menggunakan strategi 30 baris yang sama dengan yang sebelumnya. Perpustakaan template transaksi berisi detail transaksi, teman-teman yang tertarik dapat menemukan kode di inventor quantification, versi komentar di komunitas resmi 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);//轮询
    }
}

Selanjutnya adalah bagian utama dari strategi, deteksi posisi terbuka, dan operasi posisi terbuka.

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

Code sudah lelah, minum air minum berhenti~

Sebelumnya, mari kita bahas tentang prinsip penghentian slip.

Di dalam kode ini tentang penghentian geser, Anda dapat melihat beberapa contoh yang berbeda.SetStopPriceFungsi berdasarkan inputstopState(Standstill) danticker(Data pasar) untuk memperbarui harga stop loss.stopState === STATE_BUY), untuk menilai dan memperbarui harga stop loss sesuai dengan situasi yang berbeda; jikaorderStateUntuk status tidak berlaku (yaitu tidak memegang posisi yang valid), kembalikan harga stop loss saat ini. Jika harga stop loss adalah 0, inisialisasikan sebagai harga beli rata-rata dikalikan dengan(1 - stopProfit)◦ Selanjutnya, berdasarkan harga transaksi akhir ◦ticker.LastHarga yang sama untuk sahamthis.priceNilai yang berbeda dari nilai stop loss saat inithis.level) dibandingkan dengan perkalian langkah. Jika melebihi tingkat saat ini, harga stop loss diperbarui menjadi nilai setelah geser, sambil meningkatkan tingkat stop loss; jika tidak, harga stop loss saat ini tetap tidak berubah. Untuk posisi kosong.stopState === STATE_SELLLogika yang sama, tetapi mengambil nilai negatif dari perbedaan antara harga transaksi akhir dan harga saham yang sama, dan mengurangi perbedaan tersebut saat memperbarui harga stop loss. Akhirnya, kembalikan harga stop loss setelah diperbarui.

Stop loss geser adalah strategi manajemen risiko

Dalam proses kepemilikan, harga stop loss disesuaikan dengan fluktuasi harga pasar untuk mengurangi kerugian atau melindungi keuntungan. Menurut logika kode, titik-titik penting untuk mencapai stop loss slip adalah sebagai berikut:updateCurrentProfitMetode ini digunakan untuk memperbarui laba rugi saat ini, menghitung laba rugi saat ini berdasarkan kondisi kepemilikan (state) dan harga terakhir (lastPrice). Jika kepemilikan adalah keadaan jual kosong (STATE_SELL), maka laba rugi adalah selisih antara harga terbaru dan harga saham yang sama; jika multi-state (STATE_BUY), maka laba rugi adalah negatif. Metode SetStopPrice digunakan untuk memperbarui harga stop loss. Mengingat parameter yang ditransfer (stopState) dan harga terakhir (ticker.Last), penyesuaian harga stop loss. Jika keadaan stop loss kosong (STATE_FREE), maka harga stop loss saat ini tetap sama. Jika kondisi kerugian adalah banyak saham (STATE_BUY), penyesuaian harga stop loss dilakukan sesuai dengan situasi yang berbeda.1 - stopProfit), dan menetapkan kembali level stop loss menjadi 1; jika harga transaksi akhir melampaui langkah dari level saat ini, maka harga stop loss akan ditetapkan sebagai harga stop loss setelah geser, dan tingkat stop loss akan ditingkatkan; jika tidak, maka harga stop loss tidak berubah. Jika status stop loss adalah STATE_SELL, logika ini mirip.

Anda dapat mencoba kembali, dan ingat untuk menggunakan template ini untuk perpustakaan perdagangan mata uang digital.

Sumber informasi


Berkaitan

Lebih banyak

MidskyHalo pemilik, saya adalah www.banbiren.com penukar uang, penulis platform penukar uang, sedang belajar melakukan transaksi kuantitatif, saya noqq:39866099, bisakah Anda mengundang saya untuk bergabung dengan grup ini, saya tidak bisa bergabung dengan pencarian sebelumnya.

Tidak ada"Sudah banyak yang berubah".

MuiaSangat sulit.

Mimpi kecilOke ^^, Anda di sini. Langsung mendaftar, MAC QQ tidak menemukan tempat undangan >_<, 1 nomor grup: 309368835 Sekarang ada beberapa posisi.

Mimpi kecil"Sayang, aku sangat senang melihatmu".

Mimpi kecilBelajar bersama-sama.