您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java怎么實現基于資金主動性流向的交易策略”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java怎么實現基于資金主動性流向的交易策略”吧!
價格不是上就是下,長期而言,價格的漲跌概率應各是50%,那么要正確預測未來的價格,就需要實時獲取影響價格的全部因素,然后給每個因素一個正確權重,最后作出客觀理性分析。要把影響價格的全部因素羅列出來,可能會寫滿整個屏幕。
概括為:全球經濟環境、國家宏觀政策、相關產業政策、供需關系、國際事件、利率與匯率、通貨膨脹與緊縮、市場心理、未知因素等等。預測也就變成了一個工程浩大,又不可能完成的任務。所以很早的時候,我就明白市場不可預測。那么在市場中所有的預測,都變成了假設,交易也成了概率游戲,這就有意思了。
既然市場無法預測,那真的就無動于衷了嗎?不,所有的宏觀因素和微觀因素都已經反映到價格上了,也就是說價格是全部因素相互作用的結果。我們只需要分析價格,就可以做出一個完整的交易策略。
先仔細想一想,為什么價格會漲?
你可能會說,因為:國家對相關產業政策扶持、原產地又雙叒叕下暴雨了、國際貿易戰、MACD金叉了、別人都買了等等,當然這些也許都沒錯。事后看,總能找出推動價格上漲的理由。
其實,價格的漲跌類似于水漲船高。價格的上漲離不開資金的推動,盤面上,如果買的人多過賣的人,價格就會上漲。反之,如果賣的人多過買的人,價格就會下跌。有了這個概念,我們就可以根據資金凈流向反映出來的供求關系,對未來價格的走勢給出合理的預期。
與傳統分析不同的是,資金流向分析根據一段時間序列的交易數據中,分析哪些成交是資金主動流入的,哪些成交是資金主動流出。然后,把該時間段主動流入的成交量減去主動流出的成交量,便可以知道該時間段的資金凈流入。如果資金凈流入為正,表示該品種供不應求;如果資金凈流出,則表示該品種供過于求。
讀到這里,可能有人會疑問,在實際交易中,有人買有人賣才會成交。成交的單子必然是有多少買量就有多少賣量,資金進出一定是等量的。何來資金流入流出呢?其實嚴格來說,每一個買單必然對應一個相應的賣單,資金流入和資金流出一定是相等的。如果我們想要計算出哪些成交的單子是主動性買入的,哪些單子是主動性賣出的,只能用一個折中的方法,利用bar數據,根據成交量和價格來實現。
資金流向的變化準確對應著實時的市場行為,通過整合bar數據,實時計算資金凈流向。關于計算資金主動性流向有兩種算法:
第一種,如果當前單子的成交價是以對手價或超價成交的,買入成交價 >= 賣一價,代表買家更愿意以較高的價格完成交易,即計入資金主動性流入。
第二種,如果當前成交價格 > 上次成交價格,那么可以理解為,當前的成交量主動推升了價格的上漲,即計入資金主動性流入。
以上述第二種算法為例:
某個品種在 10:00 的收盤價是 3450,在 11:00 的收盤價是3455,那么我們就把 10:00 ~ 11:00 的成交量計入資金主動性流入。反之則計入資金主動性流出。而本文是在第二種方法的基礎上,加入了價格波動幅度這個因素,通過前后bar收盤價對比,把上漲或下跌的bar的成交量 * 波動幅度計入到一個序列,然后根據該序列進一步計算資金的主動性流入比率。
本文從“量”的角度來刻畫期貨市場的資金流向,通過實時分析bar數據,建立判斷短期價格走向的交易模型。一般的情況下,資金流向及價格走勢可以分為四種基本狀況:
價格上升,同時單位時間內資金主動性凈流入:這種情況下屬于強勢,未來價格繼續上升概率更大;
股價上升,同時單位時間內資金主動性凈流出:這種情況下屬于中強勢,未來價格繼續上升的速度大幅減弱;
股價下跌,同時單位時間內資金主動性凈流入:這種情況下屬于弱勢,未來價格繼續下跌概率更大;
股價下跌,同時單位時間內資金主動性凈流出:這種情況下屬于中弱勢,未來價格繼續下跌的速度大幅減弱;
主要變量,如下:
前期低點(ll)
前期高點(hh)
主動性買入(barIn)
主動性賣出(barOut)
主動流入資金與主動流出資金的比值(barRatio)
開倉閾值(openValve)
當前持倉(myAmount)
上根K線收盤價(close)
出入場條件 一個好的量化交易策略,不僅需要穩定的收益,而且能夠控制風險,在小概率時間出現時,避免出現較大虧損。在這里我們使用跟蹤主動性資金流向策略,借助短期價格預測對商品期貨行情方向進行分析,從而達到高收益、低風險的效果。 策略的步驟如下圖:
多頭開倉:如果當前無持倉,并且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怎么實現基于資金主動性流向的交易策略這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。