價格不是上是下,長期而言,價格的漲跌機率應各是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怎麼實現基於資金主動性流向的交易策略的詳細內容。更多資訊請關注PHP中文網其他相關文章!