量化の世界に連れて行きます-- MACD 双方向操作 スライド停止 コード分析

作者: リン・ハーン小さな夢, 作成日:2016-04-22 13:53:14, 更新日:2023-06-14 10:38:59

量化の世界に連れて行きます-- MACD 双方向操作 スライド停止 コード分析

この記事では,30行コードの簡素化量化戦略について説明します. この記事では,初心者が量化戦略の設計の楽しさを少しずつ発見するために,段階的に案内します. この記事では,本作はBTCの現金取引について説明します. 本作は金融,投資,証券などの分野において,以前は全く白紙でした. 将来の取引のプロセスすら理解していません. また,目玉が乱れ,耳に届かない名前や用語が混ざり,頭がおかしくなり, (その実現は,少しでも理解!少しでも理解!) 自分の百度,情報検索などで頭を埋めます. 関連コンテンツを閲覧し,基本的な概念を心に抱いて,少し理解しているJS言語と組み合わせて,シンプルに書いた.最初はK線,均線,MACD指標が何であるか理解していなかった. 簡単に言えば,K線は,市場動向を観察するための,特定の周期間の市場動向を記録する指標である.平均線は,前回の記事で使用された指標であり,MACD指標と同様に,市場動向を反映する指標である. この2つの指標の概念,アルゴリズム,公式推論など,それぞれが説明されています.理解できない方は百度で参照してください.

古い規則は,古い鳥が無視できる,先ず説明する.

変数名 初期値 解説
インターバル 2000 この変数は,プログラムが一時停止する待ち時間であるラウティングサイクルであり,単位はミリ秒で,1000ミリ秒は1秒である.したがって,この変数の初期値は2秒である.
STATE_FREE について 0 これは状態を表す変数で,空白を表します.
STATE_BUY 1 これは状態を表す変数で,複数の株を表示します.
STATE_SELL 2 状態変数,空頭保有を表示します.
ORDER_INVALID について 3 持有状態変数,持っていないことを示します.
ORDER_VALID について 4 持ってるのは...
状態 STATE_FREE について 状態変数,空白状態で初期化.
シグナル遅延 0 初期計画 信号が遅れて,一時的に役に立たない.
ストップ 利益 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のアドレスからアップロードされています. クリック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行均線策略と同じ方法で,取引テンプレートクラスライブラリを使用し,取引の詳細を包み込み,興味のある友人は発明者の量化でコードを見つけることができます.

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(市場データ) ストップ損失価格更新.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ストップ・オードは,ストップ・オードが現在のレベルを超えた場合,ストップ・オードをスライド後のストップ・オードに設定し,ストップ・オードをアップグレードします.その他の場合,ストップ・オードは変更されません.ストップ・オードが空白状態である場合,論理は類似します.init HoldOrderは,平衡後に保有情報を初期化するために使用され,保有状態,平均価格,数量,操作時間のストップ・オード,ストップ・オードを初期状態に戻します.

デジタル通貨の取引のカテゴリーを参考にしてください! 簡単に書き換えても,修正も歓迎します.

参考資料


関連性

もっと

ミッドスキー私はwww.banbiren.comの搬家家,搬家取引プラットフォームの著者です. 量的な取引を勉強しています. 私のqq番号:39866099です. グループに招待してください.

ゼロ進歩は早い〜

ミュア辛かった

小さな夢OK ^^,あなた側から直接申請してください, MAC QQは招待場所を見つけることができませんでした >_<, 1グループ番号: 309368835 現在いくつかの場所があります.

小さな夢大神指の良い~~

小さな夢共に勉強する