首頁  >  文章  >  Java  >  Java怎麼實現基於資金主動性流向的交易策略

Java怎麼實現基於資金主動性流向的交易策略

王林
王林轉載
2023-04-18 18:34:271049瀏覽
一、摘要

價格不是上是下,長期而言,價格的漲跌機率應各是50%,那麼要正確預測未來的價格,就需要即時取得影響價格的全部因素,然後給每個因素一個正確權重,最後做出客觀理性分析。要把影響價格的全部因素羅列出來,可能會寫滿整個螢幕。

概括為:全球經濟環境、國家宏觀政策、相關產業政策、供需關係、國際事件、利率與匯率、通貨膨脹與緊縮、市場心理、未知因素等等。預測也變成了一個工程浩大,又不可能的任務。所以很早的時候,我就明白市場無法預測。那麼在市場中所有的預測,都變成了假設,交易也成了機率遊戲,這就有趣了。

二、為何利用資金流向

既然市場無法預測,那真的就無動於衷了嗎?不,所有的宏觀因素和微觀因素都已經反映到價格上了,也就是說價格是全部因素相互作用的結果。我們只需要分析價格,就可以做出一個完整的交易策略。 Java怎麼實現基於資金主動性流向的交易策略

先仔細想想,為什麼價格會漲?

你可能會說,因為:國家對相關產業政策扶持、原產地又雙叒叕下暴雨了、國際貿易戰、MACD金叉了、別人都買了等等,當然這些也許都沒錯。事後看,總是能找出推動價格上漲的理由。

其實,價格的漲跌類似水漲船高。價格的上漲離不開資金的推動,盤面上,如果買的人多於賣的人,價格就會上漲。反之,如果賣的人多買的人,價格就會下跌。有了這個概念,我們就可以根據資金淨流向反映出來的供需關係,對未來價格的走勢給予合理的預期。

三、資金流向原則

與傳統分析不同的是,資金流向分析根據一段時間序列的交易資料中,分析哪些成交是資金主動流入的,哪些成交是資金主動流出。然後,將該時段主動流入的成交量減去主動流出的成交量,便可以知道該時段的資金淨流入。若資金淨流入為正,表示該品種供不應求;若資金淨流出,則表示該品種供過於求。

Java怎麼實現基於資金主動性流向的交易策略

讀到這裡,可能有人會疑問,在實際交易中,有人買有人賣才會成交。成交的單子必然是有多少買量就有多少賣量,資金進出一定是等量的。何來資金流入流出?其實嚴格來說,每一個買單必然對應一個相應的賣單,資金流入和資金流出一定是相等的。如果我們想要計算出哪些成交的單子是主動性買入的,哪些單子是主動性賣出的,只能用一個折中的方法,利用bar數據,根據成交量和價格來實現。

四、資金流向計算方法

資金流向的變化準確對應著即時的市場行為,透過整合bar數據,即時計算資金淨流向。關於計算資金主動性流向有兩種演算法:

  • 第一種,如果目前單子的成交價是以對手價或超價成交的,買入成交價>=賣一價,代表買家更願意以較高的價格完成交易,也就是計入資金主動性流入。

  • 第二種,如果當前成交價格> 上次成交價格,那麼可以理解為,當前的成交量主動推升了價格的上漲,即計入資金主動性流入。

Java怎麼實現基於資金主動性流向的交易策略

以上述第二種演算法為例:

某個品種在10:00 的收盤價是3450,在11:00 的收盤價是3455,那我們就把10:00 ~ 11:00 的成交量計入資金主動性流入。反之則計入資金主動性流出。而本文是在第二種方法的基礎上,加入了價格波動幅度這個因素,透過前後bar收盤價對比,把上漲或下跌的bar的成交量* 波動幅度計入一個序列,然後根據該序列進一步計算資金的主動性流入比率。

五、交易邏輯

本文從「量」的角度來刻畫期貨市場的資金流向,透過即時分析bar數據,建立判斷短期價格走向的交易模型。一般的情況下,資金流向及物價走勢可分為四種基本狀況:

  • 價格上升,同時單位時間內資金主動性淨流入:這種情況下屬於強勢,未來價格持續上升機率更大;

  • 股價上升,同時單位時間內資金主動性淨流出:這種情況下屬於中強勢,未來價格持續上升的速度大幅減弱;

  • 股價下跌,同時單位時間內資金主動性淨流入:這種情況下屬於弱勢,未來價格繼續下跌機率更大;

  • 股價下跌,同時單位時間內資金主動性淨流出:這種情況下屬於中弱勢,未來價格繼續下跌的速度大幅減弱; Java怎麼實現基於資金主動性流向的交易策略

主要變量,如下:

  • 前期低點(ll)

  • 前期高點(hh )

  • 主動性買進(barIn)

  • #主動性賣出(barOut)

  • 主動流入資金與主動流出資金的比值(barRatio)

  • 開倉門檻(openValve)

  • 目前持有(myAmount)

  • 上根K線收盤價(close)

#出入場條件 一個好的量化交易策略,不只需要穩定的收益,而且能夠控制風險,在小機率時間出現時,避免出現較大虧損。在這裡我們使用追蹤主動性資金流向策略,借助短期價格預測對商品期貨行情方向進行分析,從而達到高收益、低風險的效果。策略的步驟如下圖:Java怎麼實現基於資金主動性流向的交易策略

  • 多頭開倉:如果目前無持倉,並且barRatio > openValve,買進開倉;

  • #空頭開倉:如果目前無持倉,並且barRatio < 1 / openValve,賣出開倉;

  • 多頭平倉:如果目前持有多倉,並且close < ll,賣出平倉;

  • 空頭平倉:如果目前持有空倉,並且close > hh,買平倉;

六、編寫策略原始碼

取得並計算資料

function data() {
    var self = {};
    var barVol = [];
    var bars = _C(exchange.GetRecords); //获取bar数据
    if (bars.length < len * 2) { //控制bar数据数组的长度
        return;
    }
    for (var i = len; i > 0; i--) {
        var barSub_1 = bars[bars.length - (i + 1)].Close - bars[bars.length - (i + 2)].Close; //计算当前收盘价与上个bar收盘价的价差
        if (barSub_1 > 0) { //如果价格涨了,就在数组里面添加正数
            barVol.push(bars[bars.length - (i + 1)].Volume * (bars[bars.length - (i + 1)].High - bars[bars.length - (i + 1)].Low));
        } else if (barSub_1 < 0) { //如果价格跌了,就在数组里面添加负数
            barVol.push(-bars[bars.length - (i + 1)].Volume * (bars[bars.length - (i + 1)].High - bars[bars.length - (i + 1)].Low));
        }
    }
    if (barVol.length > len) {
        barVol.shift(); //释放多余的数据
    }
    self.barIn = 0;
    self.barOut = 0;
    for (var v = 0; v < barVol.length; v++) {
        if (barVol[v] > 0) {
            self.barIn += barVol[v]; //合并全部主动流入的资金
        } else {
            self.barOut -= barVol[v]; //合并全部主动流出的资金
        }
    }
    self.barRatio = self.barIn / Math.abs(self.barOut); //计算主动流入资金与主动流出资金的比值
    bars.pop(); //删除未结束的bar数据
    self.close = bars[bars.length - 1].Close; //获取上根K线的收盘价
    self.hh = TA.Highest(bars, hgLen, 'High'); //获取前高
    self.ll = TA.Lowest(bars, hgLen, 'Low'); //获取前低
    return self;
}

透過發明者量化API中的GetRecords方法,直接取得bar資料。包含最高價、最低價、開盤價、收盤價、成交量、標準時間戳記。如果最新的成交價大於上次的成交價,那麼就把最新的成交量* (最高價- 最低價)計入主動性買入;如果最新的成交價小於上次的成交價,那麼就把最新的成交量*(最高價- 最低價)計入主動性賣出;

取得持股資料

function positions(name) {
    var self = {};
    var mp = _C(exchange.GetPosition); //获取持仓
    if (mp.length == 0) {
        self.amount = 0;
    }
    for (var i = 0; i < mp.length; i++) { //持仓数据处理
        if (mp[i].ContractType == name) {
            if (mp[i].Type == PD_LONG || mp[i].Type == PD_LONG_YD) {
                self.amount = mp[i].Amount;
            } else if (mp[i].Type == PD_SHORT || mp[i].Type == PD_SHORT_YD) {
                self.amount = -mp[i].Amount;
            }
            self.profit = mp[i].Profit;
        } else {
            self.amount = 0;
        }
    }
    return self;
}

透過發明者量化API中的GetPosition方法取得基礎持倉數據,並對這些基礎數據進一步處理,如果當前持有多單,那麼就返回正持倉數量;如果當前持有空單,那麼就返回負持倉數量。這樣做的目的是方便計算開平倉邏輯。

下單交易

function trade() {
    var myData = data(); //执行data函数
    if (!myData) {
        return;
    }
    var mp = positions(contractType); //获取持仓信息
    var myAmount = mp.amount; //获取持仓数量
    var myProfit = mp.profit; //获取持仓浮动盈亏
    if (myAmount > 0 && myData.close < myData.ll) {
        p.Cover(contractType, unit); //多头平仓
    }
    if (myAmount < 0 && myData.close > myData.hh) {
        p.Cover(contractType, unit); //空头平仓
    }
    if (myAmount == 0) {
        if (myData.barRatio > openValve) {
            p.OpenLong(contractType, unit); //多头开仓
        } else if (myData.barRatio < 1 / openValve) {
            p.OpenShort(contractType, unit); //空头开仓
        }
    }
}
七、策略特點

特點:

##核心參數少:模型設計思路清晰,核心參數只有3個。可優化空間很小,可以有效避免過度擬合。較強的普適性:策略邏輯簡單,具有高普適性,除農產品外適應大部分品種,可進行多品種組合。

改進:

加入持股條件:單向(股票)市場資金流向可以根據價格漲跌、成交量等因素來界定資金的流入或流出。但是,由於該策略並沒有加入持倉量這個條件,使得統計主動性資金流向可能會失真。

加入標準差條件:僅依靠資金流向來做開倉條件,可能會出現頻繁的假訊號,造成頻繁開平倉。透過統計指定時間內的資金淨流出的平均值,上下加上標準差,來過濾虛假訊號。

完整策略原始碼:
/*backtest
start: 2016-01-01 09:00:00
end: 2019-12-31 15:00:00
period: 1h
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/

var p = $.NewPositionManager(); //调用商品期货交易类库

//持仓数据处理
function positions(name) {
    var self = {};
    var mp = _C(exchange.GetPosition); //获取持仓
    if (mp.length == 0) {
        self.amount = 0;
    }
    for (var i = 0; i < mp.length; i++) { //持仓数据处理
        if (mp[i].ContractType == name) {
            if (mp[i].Type == PD_LONG || mp[i].Type == PD_LONG_YD) {
                self.amount = mp[i].Amount;
            } else if (mp[i].Type == PD_SHORT || mp[i].Type == PD_SHORT_YD) {
                self.amount = -mp[i].Amount;
            }
            self.profit = mp[i].Profit;
        } else {
            self.amount = 0;
        }
    }
    return self;
}

//行情数据处理函数
function data() {
    var self = {};
    var barVol = [];
    var bars = _C(exchange.GetRecords); //获取bar数据
    if (bars.length < len * 2) { //控制bar数据数组的长度
        return;
    }
    for (var i = len; i > 0; i--) {
        var barSub_1 = bars[bars.length - (i + 1)].Close - bars[bars.length - (i + 2)].Close; //计算当前收盘价与上个bar收盘价的价差
        if (barSub_1 > 0) { //如果价格涨了,就在数组里面添加正数
            barVol.push(bars[bars.length - (i + 1)].Volume * (bars[bars.length - (i + 1)].High - bars[bars.length - (i + 1)].Low));
        } else if (barSub_1 < 0) { //如果价格跌了,就在数组里面添加负数
            barVol.push(-bars[bars.length - (i + 1)].Volume * (bars[bars.length - (i + 1)].High - bars[bars.length - (i + 1)].Low));
        }
    }
    if (barVol.length > len) {
        barVol.shift(); //释放多余的数据
    }
    self.barIn = 0;
    self.barOut = 0;
    for (var v = 0; v < barVol.length; v++) {
        if (barVol[v] > 0) {
            self.barIn += barVol[v]; //合并全部主动流入的资金
        } else {
            self.barOut -= barVol[v]; //合并全部主动流出的资金
        }
    }
    self.barRatio = self.barIn / Math.abs(self.barOut); //计算主动流入资金与主动流出资金的比值
    bars.pop(); //删除未结束的bar数据
    self.close = bars[bars.length - 1].Close; //获取上根K线的收盘价
    self.hh = TA.Highest(bars, hgLen, 'High'); //获取前高
    self.ll = TA.Lowest(bars, hgLen, 'Low'); //获取前低
    return self;
}

//交易函数
function trade() {
    var myData = data(); //执行data函数
    if (!myData) {
        return;
    }
    var mp = positions(contractType); //获取持仓信息
    var myAmount = mp.amount; //获取持仓数量
    var myProfit = mp.profit; //获取持仓浮动盈亏
    if (myAmount > 0 && myData.close < myData.ll) {
        p.Cover(contractType, unit); //多头平仓
    }
    if (myAmount < 0 && myData.close > myData.hh) {
        p.Cover(contractType, unit); //空头平仓
    }
    if (myAmount == 0) {
        if (myData.barRatio > openValve) {
            p.OpenLong(contractType, unit); //多头开仓
        } else if (myData.barRatio < 1 / openValve) {
            p.OpenShort(contractType, unit); //空头开仓
        }
    }
}

//程序主入口,从这里启动
function main() {
    while (true) { //进入循环
        if (exchange.IO("status")) { //如果是开市时间
            _C(exchange.SetContractType, contractType); //订阅合约
            trade(); //执行trade函数
        }
    }
}
八、策略回測

#策略配置: Java怎麼實現基於資金主動性流向的交易策略回測績效: Java怎麼實現基於資金主動性流向的交易策略Java怎麼實現基於資金主動性流向的交易策略#

以上是Java怎麼實現基於資金主動性流向的交易策略的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除