精华内容
下载资源
问答
  • 基于深度学习算法的高频交易策略及其盈利能力_孙达昌.pdf
  • 基于深度学习算法的高频交易策略及其盈利能力.pdf
  • 基于变量选择和遗传网络规划的期货高频交易策略研究_陈艳 基于变量选择和遗传网络规划的期货高频交易策略研究_陈艳 基于变量选择和遗传网络规划的期货高频交易策略研究_陈艳
  • 电子市场已成为交易各种金融资产的热门场所,基于计算机的算法交易也已成为全球金融市场的主导力量。 识别和理解算法交易对... 这些经验测试的结果表明,可以基于对单个交易行为的观察来准确地识别和分析高频交易策略
  • ChannelBreakOutHFT 高频交易的渠道突破策略。 来自此的存储库如下。
  • C++商品期货高频交易策略之Penny Jump

    千次阅读 2019-09-06 11:16:22
    高频交易中,主要分为两类策略。分别是买方策略和卖方策略,卖方策略通常都是做市策略,并且这两类策略互为对手。比如:以最快速度抹平市场的一切不合理现象的高频套利买方策略,仗着速度快主动出击,或者吃掉其它...

    摘要

    市场就是江湖,买方和卖方永远在博弈,这也是交易的永恒主题。今天给大家分享的 Penny Jump 策略属于HFT高频策略之一,最初来源于银行间外汇市场,常用于主流货币对做市。

    高频策略分类

    在高频交易中,主要分为两类策略。分别是买方策略和卖方策略,卖方策略通常都是做市策略,并且这两类策略互为对手。比如:以最快速度抹平市场的一切不合理现象的高频套利买方策略,仗着速度快主动出击,或者吃掉其它做市商的错价。

    还有一种,通过分析历史数据或盘口订单规律,提前在不合理的价位埋伏挂单,并随着盘口价格快速变化挂撤单,这类策略常见于被动做市,一旦自己挂单被成交,并且有一定利润或者达到止盈止损条件后平仓了结。被动做市策略通常对速度的要求不是太苛刻,更多的需要策略逻辑和结构。

    什么是 Penny Jump 策略

    Penny Jump 翻译成中文就是微量加价的意思,其原理是跟踪盘口买价和卖价,然后不停的根据盘口价格加上或减去微量价格挂单,很明显这是一个被动成交的挂单策略,属于卖方做市策略的一种。它的业务模式和商业逻辑是在交易所挂限价单进行双边交易以提供流动性。

    做市策略要求手中有一定量存货,然后同时在买方和卖方双边交易。这种策略的主要收入是交易所提供的做市返还,另外还有做市时低买高卖所赚取的价差。但是对于很多以做市为目的的高频交易商来说,赚取买卖价差虽然是件美好的事,但并不是绝对需要的盈利手段。

    Penny Jump 策略原理

    我们知道交易市场有许多散户,也有很多大户,比如:游资、公募基金、私募基金等等。散户的资金通常较少,盘口附件的订单就足够交易了,很随意就能买卖一只交易品种。但是大户想要买进或者卖出,就没有这么简单了。

    假如一个大户想要买进500手原油,盘口附近根本就没有这么多订单,又不想以市价单买进,那样滑价成本就太大了,所以只能在市场中排队买入,此时市场里面所有的参与者都看到在盘口的买方,有个巨大的订单。

    因为这种巨大的订单,在市场里面看起来笨手笨脚的,有时候我们戏称为“大象,elephant”。举个例子,本来市场的盘口数据应该是:卖价400.3,量50;买价400.1,量10。突然这个笨重的大象进场了,买单挂在了400.1的价位。此时盘口数据就变为:卖价400.3,量50;买价400.1,量510。

    做交易的朋友都知道,如果一个价位有一个巨量的挂单,那么这个价位就会形成很强的支撑力。当然高频交易者也知道,所以他们会在买一价之上挂买单,那么盘口数据就变为:卖价400.3,量50;买价400.2,量1,400.1的订单变成了买二。那么如果价格上涨至400.3,高频交易者就会赚到0.1的利润。

    即便价格没有上涨,在买二这个位置,还有一直“大象”在撑着,也可以很快的反手以400.1的价格卖给这只大象。这就是 Penny Jump 策略。它的策略逻辑就是这么简单,通过监控市场盘口订单状态,来揣测交易对手的意图,然后抢先他人一步建立有利的部位,最后在短时间内以微小的价差获利了结。对于这只“大象”来说,他因为在市场里面挂了一张巨量的买单,所以暴露了他的交易意图,自然就变成高频交易者猎杀的目标。

    Penny Jump 策略实现

    首先,观察盘口出现概率极低的交易机会,并根据交易逻辑做出相应策略。如果逻辑复杂,就需要利用现有的数学知识,尽可能的用模型描述不合理现象的本质,并且尽量减少拟合。此外还必须用可以见价成交、见量成交的回测引擎去验证。发明者量化目前是唯一支持这两种回测模式的平台。

    什么是见价成交和见量成交?见价成交你可以理解为:你的挂单是400.1买入,只有卖单为400.1甚至更低的时候,你的挂单才能成交。它只计算盘口挂单价格数据,而不计算盘口挂单量数据,只符合交易所撮合规则中的价格优先。

    见量成交是见价成交的升级版,它既符合价格优先,又符合时间优先,可以说这种撮合模式,与交易所的撮合模式一模一样。通过计算盘口挂单量,来判断当前挂单是否达到被动成交的条件实现见量成交,以此做到真正的模拟实盘环境。

    另外,细心的朋友可能会发现 Penny Jump 策略需要市场交易机会的支持,即:盘口至少有两跳的价格空挡。正常情况下商品期货主力合约交易比较频繁,盘口买一与卖一只有一跳的价差,几乎没有下手机会。所以我们把精力放到交易不是太活跃的次主力合约上面,次主力合约偶尔会有两跳甚至三跳的机会出现。比如在MA次主力909合约的盘口就出现下面这种情况:

    卖一为2225量551,买一2223量565,向下看几秒,出现这种情况后,几个tick推送后消失,这种情况,我们视为市场的自我纠正,我们要做的就是赶在市场主动纠正前,杀进去,这种逻辑看人工去盯盘是天方夜谈,因为商品期货盘口差价两跳的情况级少出现,三跳最安全,但三跳极少出现,导致交易频率太低,意义不大。

    接下来,我们观察盘口之前卖一买一与现在两跳时买一卖一的区别,去填补盘口差价空隙,如果速度够快,就可以排在委托单的最前位置,做为Maker以最快的速度成交后反手卖出,持仓时间很短,有了这个交易逻辑,实现为策略以后,以MA909为例,实盘测试推荐易盛而非CTP接口,易盛仓位与资金变化是推送机制,非常适合高频。

    策略源码

    理清交易逻辑后,我们就可以用代码去实现了,由于发明者量化平台的C++例子很少,这里就用C++写本策略,方便大家学习,品种还是商品期货。首先依次打开:fmz.com > 登录 > 控制中心 > 策略库 > 新建策略 > 点击左上角下拉菜单 > 选择C++,开始编写策略,注意看下面代码中的注释。

    第1步:先把策略的框架搭建起来,在这个策略中定义了一个HFT类和一个main主函数。在main主函数里面的第1行是清除日志,这样做的目的是每次策略重启的时候,把之前运行的日志信息清除;第2行是过滤一些没有必要提示的错误信息,比如因网络延迟暂时过高,出现的一些提示,这样可以使日志只记录重要的信息,看起来更加整洁;第3行是打印“Init OK”信息,意思是说已经开始启动程序,当然你还可以改成别的,比如“印钞机已经开始启动”;第4行是根据HFT类来创建一个对象,并且对象的名字是hft;第5行程序进入了while无限循环模式,并且一直执行对象hft中的Loop方法,可见Loop方法一定是这个程序的核心逻辑。第6行又是一个打印信息,正常情况下,程序是不会执行到第6行的,如果程序执行到第6行,证明程序已经结束了。

    接下来,我们来看下HFT类,这个类中共有5个方法。第1个方法是构造方法,这个不必多说;第2个方法是获取当前是星期几,用来判断是否为新的K线;第3个方法主要是取消所有未成交的订单,以及获取详细的持仓信息,因为在下单交易之前,肯定要先判断当前的持仓状态;第4个方法主要用来打印一些信息,对于这个策略来说,这个方法不是主要的;最主要的是第5个方法,这个方法主要负责处理交易逻辑和下单交易。

    // 定义HFT类
    class HFT {
        public:
            HFT() {
                // 构造函数
            }
            
            int getTradingWeekDay() {
                // 获取当前是星期几,用来判断是否为新的K线
            }
            
            State getState() {
                // 获取订单数据
            }
    
            void stop() {
                // 打印订单和持仓            
            }
            
            bool Loop() {
                // 策略逻辑和下单    
            }
    };
    
    // 主函数
    void main() {
        LogReset();  // 清除日志
        SetErrorFilter("ready|timeout");  // 过滤错误信息
        Log("Init OK");  // 打印日志
        HFT hft;  // 创建HFT对象
        while (hft.Loop());  // 进入无线循环模式
        Log("Exit");  // 程序退出,打印日志
    }
    

    那么我们来看下,这个HFT类中的每个方法都是怎么具体实现的,以及最核心的Loop方法究竟是怎么工作的。我们从上到下把每个方法的具体实现方式,一个一个过一遍,你就会发现原来高频策略这么简单。在讲HFT这个类之前,首先我们定义了几个全局变量,用于存储hft对象计算后的结果。它们分别是:存储订单状态、持仓状态、持多单方向、持空单方向、买价、买量、卖价、卖量。请看下面的代码:

    // 定义全局枚举类型State
    enum State {
        STATE_NA,  // 储存订单状态
        STATE_IDLE,  // 储存持仓状态
        STATE_HOLD_LONG,  // 储存持多单方向
        STATE_HOLD_SHORT,  // 储存持空单方向
    };
    
    // 定义全局浮点类型变量
    typedef struct {
        double bidPrice;  // 储存买价
        double bidAmount;  // 储存买量
        double askPrice;  // 储存卖价
        double askAmount;  // 储存卖量
    } Book;
    

    有了以上全局变量,我们就可以把hft对象所计算的结果分别存储起来,方便程序后续调用。OK接着我们讲下HFT类中的每个方法的具体实现。首先第1个HFT方法是一个构造函数,它调用第2个getTradingWeekDay方法,并把结果过打印到日志中;第2个getTradingWeekDay方法是获取当前是星期几,用来判断是否为新的K线,实现起来也很简单,获取时间戳,计算出小时和周,最后返回星期数;第3个getState方法有点长,这里不再一行一行去解释,而是自上而下描述它的主要功能,具体可以在下面的策略中看注释,先获取了所有订单,返回的结果是一个普通数组,然后遍历这个数据,一个一个去取消订单,紧接着获取持仓数据,返回来的也是一个数组,然后遍历这个数组,获取详细的持仓信息,包括:方向、持仓量、昨仓还是今仓等等,最后返回结果;第4个stop方法是打印一些信息,这里不再赘述;代码如下:

    public:
        // 构造函数
        HFT() {
            _tradingDay = getTradingWeekDay();
            Log("current trading weekday", _tradingDay);
        }
        
        // 获取当前是星期几,用来判断是否为新的K线
        int getTradingWeekDay() {
            int seconds = Unix() + 28800;  // 获取时间戳
            int hour = (seconds/3600)%24;  // 小时
            int weekDay = (seconds/(60*60*24))%7+4;  // 星期
            if (hour > 20) {
                weekDay += 1;
            }
            return weekDay;
        }
        
        // 获取订单数据
        State getState() {
            auto orders = exchange.GetOrders();  // 获取所有订单
            if (!orders.Valid || orders.size() == 2) {  // 如果没有订单或者订单数据的长度等于2
                return STATE_NA;
            }
            
            bool foundCover = false;  // 临时变量,用来控制取消所有未成交的订单
            // 遍历订单数组,取消所有未成交的订单
            for (auto &order : orders) {
                if (order.Id == _coverId) {
                    if ((order.Type == ORDER_TYPE_BUY && order.Price < _book.bidPrice - _toleratePrice) ||
                        (order.Type == ORDER_TYPE_SELL && order.Price > _book.askPrice + _toleratePrice)) {
                        exchange.CancelOrder(order.Id, "Cancel Cover Order");  // 根据订单ID取消订单
                        _countCancel++;
                        _countRetry++;
                    } else {
                        foundCover = true;
                    }
                } else {
                    exchange.CancelOrder(order.Id);  // 根据订单ID取消订单
                    _countCancel++;
                }
            }
            if (foundCover) {
                return STATE_NA;
            }
            
            // 获取持仓数据
            auto positions = exchange.GetPosition();  // 获取持仓数据
            if (!positions.Valid) {  // 如果持仓数据为空
                return STATE_NA;
            }
    
            // 遍历持仓数组,获取具体的持仓信息
            for (auto &pos : positions) {
                if (pos.ContractType == Symbol) {
                    _holdPrice = pos.Price;
                    _holdAmount = pos.Amount;
                    _holdType = pos.Type;
                    return pos.Type == PD_LONG || pos.Type == PD_LONG_YD ? STATE_HOLD_LONG : STATE_HOLD_SHORT; 
                }
            }
            return STATE_IDLE;
        }
        
        // 打印订单和持仓
        void stop() {
            Log(exchange.GetOrders());  // 打印订单
            Log(exchange.GetPosition());  // 打印持仓
            Log("Stop");
        }
    

    最后我们着重讲解Loop函数是怎么控制策略逻辑以及下单的,想看得更仔细的小伙伴可以参考代码中的注释。首先判断CTP交易和行情服务器是否连接;接着获取账户的可用余额以及获取星期数;接着设置要交易的品种代码,具体做法是调用发明者量化官方的SetContractType函数,并且可以利用这个函数返回品种的详细信息;然后调用GetDepth函数,获取当前市场的深度数据,深度数据包括:买价、买量、卖价、卖量等等,并且我们用变量把它们存储起来,因为待会还要用到;再然后把这些盘口数据输出到状态栏,方便用户观看当前的市场状态;代码如下:

    // 策略逻辑和下单
    bool Loop() {
        if (exchange.IO("status") == 0) {  // 如果CTP交易和行情服务器已经连接
            LogStatus(_D(), "Server not connect ....");  // 打印信息到状态栏
            Sleep(1000);  // 休眠1秒
            return true;
        }
        
        if (_initBalance == 0) {
            _initBalance = _C(exchange.GetAccount).Balance;  // 获取账户余额
        }
        
        auto day = getTradingWeekDay();  // 获取星期数
        if (day != _tradingDay) {
            _tradingDay = day;
            _countCancel = 0;
        }
        
        // 设置期货合约类型,并获取合约具体信息
        if (_ct.is_null()) {
            Log(_D(), "subscribe", Symbol);  // 打印日志
            _ct = exchange.SetContractType(Symbol);  // 设置期货合约类型
            if (!_ct.is_null()) {
                auto obj = _ct["Commodity"]["CommodityTickSize"];
                int volumeMultiple = 1;
                if (obj.is_null()) { // CTP
                    obj = _ct["PriceTick"];
                    volumeMultiple = _ct["VolumeMultiple"];
                    _exchangeId = _ct["ExchangeID"];
                } else { // Esunny
                    volumeMultiple = _ct["Commodity"]["ContractSize"];
                    _exchangeId = _ct["Commodity"]["ExchangeNo"];
                }
                if (obj.is_null() || obj <= 0) {
                    Panic("PriceTick not found");
                }
                if (_priceTick < 1) {
                    exchange.SetPrecision(1, 0);  // 设置价格与品种下单量的小数位精度, 设置后会自动截断
                }
                _priceTick = double(obj);
                _toleratePrice = _priceTick * TolerateTick;
                _ins = _ct["InstrumentID"];
                Log(_ins, _exchangeId, "PriceTick:", _priceTick, "VolumeMultiple:", volumeMultiple);  // 打印日志
            }
            Sleep(1000);  // 休眠1秒
            return true;
        }
        
        // 检查订单和头寸以设置状态
        auto depth = exchange.GetDepth();  // 获取深度数据
        if (!depth.Valid) {  // 如果没有获取到深度数据
            LogStatus(_D(), "Market not ready");  // 打印状态信息
            Sleep(1000);  // 休眠1秒
            return true;
        }
        _countTick++;
        _preBook = _book;
        _book.bidPrice = depth.Bids[0].Price;  // 买一价
        _book.bidAmount = depth.Bids[0].Amount;  // 买一量
        _book.askPrice = depth.Asks[0].Price;  // 卖一价
        _book.askAmount = depth.Asks[0].Amount;  // 卖一量
        // 判断盘口数据赋值状态
        if (_preBook.bidAmount == 0) {
            return true;
        }
        auto st = getState();  // 获取订单数据
        
        // 打印盘口数据到状态栏
        LogStatus(_D(), _ins, "State:", st, 
                    "Ask:", depth.Asks[0].Price, depth.Asks[0].Amount, 
                    "Bid:", depth.Bids[0].Price, depth.Bids[0].Amount,
                    "Cancel:", _countCancel,
                    "Tick:", _countTick);
    }
    

    以上做了这么多铺垫,最后终于可以下单交易了,在交易之前,首先判断当前程序的持仓状态(空仓、多单、空单),这里用到了if…else if…else if,逻辑很简单如果空仓就开仓,如果有多单就按条件平多单,如果有空单,就按条件平空单。为了便于大家理解,这里讲分三段讲解,先讲开仓:

    首先声明一个布尔值变量,记录开仓次数,用来控制平仓次数;然后获取当前账户信息,并记录盈利值,接着判断撤单状态,如果撤单超过设置的最大值,就在日志中打印相关信息;然后计算当前买价与卖价差的绝对值,来判断当前盘口买价与卖价之间是否有2跳以上的空间;紧接着获取买一价和卖一价,如果之前的买价大于当前的买价,并且当前的卖量小于买量,证明买一消失,就设置多单开仓价格和下单量;否则如果之前的卖价小于当前的卖价,并且当前买量小于卖量,证明价格卖一消失,就设置空单开仓价格和下单量;最后多单和空单同时进场。具体代码如下:

    bool forceCover = _countRetry >= _retryMax;  // 布尔值,用来控制平仓次数
    if (st == STATE_IDLE) {  // 如果无持仓
        if (_holdAmount > 0) {
            if (_countRetry > 0) {
                _countLoss++;  // 失败计数
            } else {
                _countWin++;  // 成功技术
            }
            auto account = exchange.GetAccount();  // 获取账户信息
            if (account.Valid) {  // 如果获取到账户信息
                LogProfit(_N(account.Balance+account.FrozenBalance-_initBalance, 2), "Win:", _countWin, "Loss:", _countLoss);  // 记录盈利值
            }
        }
        _countRetry = 0;
        _holdAmount = 0;
        
        // 判断撤单状态
        if (_countCancel > _cancelMax) {
            Log("Cancel Exceed", _countCancel);  // 打印日志
            return false;
        }
    
        bool canDo = false;  // 临时变量
        if (abs(_book.bidPrice - _book.askPrice) > _priceTick * 1) {  // 如果当前盘口买价与卖价之间是否有2跳以上的空间
            canDo = true;
        }
        if (!canDo) {
            return true;
        }
        
        auto bidPrice = depth.Bids[0].Price;  // 买一价
        auto askPrice = depth.Asks[0].Price;  // 卖一价
        auto bidAmount = 1.0;
        auto askAmount = 1.0;
        
        if (_preBook.bidPrice > _book.bidPrice && _book.askAmount < _book.bidAmount) {  // 如果之前的买价大于当前的买价,并且当前的卖量小于买量
            bidPrice += _priceTick;  // 设置开多单价格
            bidAmount = 2;  // 设置开多单量
        } else if (_preBook.askPrice < _book.askPrice && _book.bidAmount < _book.askAmount) {  // 如果之前的卖价小于当前的卖价,并且当前买量小于卖量
            askPrice -= _priceTick;  // 设置开空单价格
            askAmount = 2;  // 设置开空单量
        } else {
            return true;
        }
        Log(_book.bidPrice, _book.bidAmount, _book.askPrice, _book.askAmount);  // 打印当前盘口数据
        exchange.SetDirection("buy");  // 设置下单类型为多头
        exchange.Buy(bidPrice, bidAmount);  // 多头买入开仓
        exchange.SetDirection("sell");  // 设置下单类型为空头
        exchange.Sell(askPrice, askAmount);  // 空头卖出开仓
    }
    

    接着我们讲如何平多单,首先根据当前的持仓状态,设置下单类型,及平昨仓或平今仓,然后获取卖一价,如果当前卖一价大于多单开仓价格,就设置平多单的价格。如果当前卖一价小于多单开仓价格,就重置平仓次数变量为真,接着平掉所有的多单,最后为了保险起见,再来判断平仓是否成功。代码如下:

    else if (st == STATE_HOLD_LONG) {  // 如果持多单
        exchange.SetDirection((_holdType == PD_LONG && _exchangeId == "SHFE") ? "closebuy_today" : "closebuy");  // 设置下单类型,及平昨仓或平今仓
        auto sellPrice = depth.Asks[0].Price;  // 获取卖一价
        if (sellPrice > _holdPrice) {  // 如果当前卖一价大于多单开仓价格
            Log(_holdPrice, "Hit #ff0000");  // 打印多单开仓价格
            sellPrice = _holdPrice + ProfitTick;  // 设置平多单价格
        } else if (sellPrice < _holdPrice) {  // 如果当前卖一价小于多单开仓价格
            forceCover = true;
        }
        if (forceCover) {
            Log("StopLoss");
        }
        _coverId = exchange.Sell(forceCover ? depth.Bids[0].Price : sellPrice, _holdAmount);  // 平多单
        if (!_coverId.Valid) {
            return false;
        }
    }
    

    最后我们来看下是如何平空单的,原理跟上面的平多单刚好相反,首先根据当前的持仓状态,设置下单类型,及平昨仓或平今仓,然后获取买一价,如果当前买一价小于空单开仓价格,就设置平空单的价格。如果当前买一价大于空单开仓价格,就重置平仓次数变量为真,接着平掉所有的空单,最后为了保险起见,再来判断平仓是否成功。

    else if (st == STATE_HOLD_SHORT) {  // 如果持空单
        exchange.SetDirection((_holdType == PD_SHORT && _exchangeId == "SHFE") ? "closesell_today" : "closesell");  // 设置下单类型,及平昨仓或平今仓
        auto buyPrice = depth.Bids[0].Price;  // 获取买一价
        if (buyPrice < _holdPrice) {  // 如果当前买一价小于空单开仓价格
            Log(_holdPrice, "Hit #ff0000");  // 打印日志
            buyPrice = _holdPrice - ProfitTick;  // 设置平空单价格
        } else if (buyPrice > _holdPrice) {  // 如果当前买一价大于空单开仓价格
            forceCover = true;
        }
        if (forceCover) {
            Log("StopLoss");
        }
        _coverId = exchange.Buy(forceCover ? depth.Asks[0].Price : buyPrice, _holdAmount);  // 平空单
        if (!_coverId.Valid) {
            return false;
        }
    }
    

    以上就是这个策略完整的解析,俗话说看十遍不如动手一遍,点击复制完整策略源代码,无需配置在线回测。

    回测结果

    交易逻辑

    策略声明

    为满足对高频交易的好奇心,为了更明显的看到结果,此策略回测手续费设定为0,实现了一个简单的拼速度逻辑,想要覆盖手续费实现盈利,实盘需做更多优化,仅凭这个简单的逻辑很难致胜,要考虑更多操作,比如锁仓(降低平今手续费),利用定单薄流进行短期预测提高胜率,再加上交易所手续费返还,从而实现一个可持久盈利的策略,关于高频交易的书籍很多,希望大家多去思考,多去实盘,而不是只停留在原理上。

    关于我们

    发明者量化是一个纯技术驱动的团队,为量化交易爱好者提供了一个高可用的回测机制,我们的回测机制是真实的模拟了一个交易所的存在,而不是简单的见价撮合,希望用户能够利用到平台的优点更好的去发挥自己的能力。

    展开全文
  • 看看常见的高频交易策略都有哪些套路 目前市场上高频交易策略五花八门。比较常见的策略包括以下四种: 1, 套利策略 2, 盘口策略 3, 做市策略 4, 事件驱动 一,套利策略: 一个理想的套利策略是各种情境...

    想在交易竞赛中占据先机?看看常见的高频交易策略都有哪些套路

     


    目前市场上高频交易策略五花八门。比较常见的策略包括以下四种:

    1,  套利策略

    2,  盘口策略

    3,  做市策略

    4,  事件驱动

    一,套利策略:

    一个理想的套利策略是各种情境下,预期收益始终为正的策略,比如当一个期货品种出现了期货价格大幅高于可交割现货价格,投资者如果选择卖出期货合约,并使用现货交割,在扣除所有交易和交割成本后,仍有正收益时,即出现了一个无风险套利机会。又比如,当两个交易所交易的同一种商品(比如上海黄金交易所的黄金和上海期货交易所的同品级黄金)出现了大幅的价格偏离,从一个交易所买入对应合约、交割、再抛售到另一个交易所,扣除所有交易和交割成本时,仍有利可图,这也是一个无风险套利机会。

    当然,这类无风险套利机会本身比较稀少,且涉及到交割成本的计算,操作并不简单。多数投资者从事的是另一种并非“无风险”的套利,也就是“统计套利”。统计套利也是以两个或多个品种的价差为交易信号,其原理是两个历史价格高度相关的品种,其价差一般会有一个相对固定的波动范围,当价差大幅偏离这个历史范围时,价差有较高的概率在一定时间后(理想的状况是很短的时间内)回归”正常范围“。

    当价差显著高于正常范围时,即可以做空该价差。当价差显著低于该范围时,即可以做多该价差。当价差回归到“正常范围”时即可获利平仓。

    统计套利一般需要交易价格相关性较高的品种,根据交易品种的选取不同,还可以分为:

    1,  同品种跨交易所套利。比如上海黄金交易所和上海期货交易所的同品级黄金。

    2,  同品种跨月套利。比如上海期货交易所4月和5月的铜期货,同一标的行权价相同而行权月份不同的期权合约。

    3,  跨品种套利。比如豆粕和菜粕期货,螺纹钢和热卷期货。

     

    这三种统计套利的风险会随着交易标的价格相关度的下降而增加。投资者可以优先选择价格相关性较高的套利组合进行交易。另外,投资者也应注意,随着交易时间周期的缩短(比如由日线级别缩短到分钟级别),能干扰价差运行的因素也会减少。多数可以干扰日线级别价格运行的因素(往往是宏观的因素)无法影响到分钟级别的价格运行,所以在较短周期上进行套利交易操作会更加安全。这也是越来越多的投资者开始短周期程序化交易的原因。

    二,盘口策略:

    这类高频交易策略重在发现各种盘口数据变动与价格变动的规律。比如一个品种,某一时刻,买入委托显著多于卖出委托后,价格将如何变化。或者一个品种,某一时段,成交量显著放大后价格将如何变化。再比如,某一品种的某些价格或成交量的某些变化出现后,将对另一个品种的价格产生怎样的影响。

    投资者一般通过分析大量历史数据,发现规律,归纳有效信号,设计策略。这些策略可以在市场盘口数据出现类似信号后迅速进行交易。

    三,做市策略:

    做市交易旨在为某些不够活跃的品种从提供流动性,比如当市场买卖价差较大时,做市商以一个相对现有卖盘更低的价格与买盘成交,并以一个相对现有买盘更高的价格与卖盘成交,使得交易达成。作为提高市场流动性的报酬,交易所通常会给指定的做市商手续费、市场数据方面的优惠,以及交易速度、特殊交易指令方面的支持,使得做市交易变得有利可图。

    虽然在中国市场上,绝大多数投资者无法申请到做市商资格,但部分高频交易者也采用近似做市策略的盘口策略来通过买卖盘间变动的价差来获利。

     

    四,事件驱动:

    事件驱动通常由投资者总结了一些事件对某些品种价格产生影响的规律,并在发生类似事件后迅速对品种进行交易。这些事件包罗万象,从统计局公布经济数据、美联储议息会议报告、美国农业部的供需报告、分析师对公司的评级、公司财报、领导人讲话、自然灾害等等。

    随着自然语言分析工具的普及和网络速度的提升,越来越多的投资者可以参与到事件驱动策略中来。

    我们今后还会更详细地介绍各种策略的实现细节。希望这些策略简介能给您一些启发,有朝一日也能够开发出自己的高频交易策略,在量化交易的竞技场里占据先机。

    — — — — — — E N D — — — — — —

    往期文章:

    Numpy处理tick级别数据技巧

    真正赚钱的期权策略曲线是这样的

    多品种历史波动率计算

    如何实现全市场自动盯盘

    AI是怎样看懂研报的

    真格量化策略debug秘籍

    真格量化对接实盘交易

    真格量化可访问:

    https://51zhenge.com

    真格量化微信公众号,长按关注:

    遇到了技术问题?欢迎加入真格量化Python技术交流QQ群  726895887

    展开全文
  • A industrial high-performance High Frequency Trading System by C 11, support CTP, Femas and so on. 基于C 11开发的量化交易平台,可实现CTP、飞马等平台的高频交易策略
  • 原帖地址:https://www.fmz.com/bbs-topic/1184在商品期货高频交易策略中, Tick行情的接收速度对策略的盈利结果有着决定性的影响,但市面上大多数交易框架,都是采用回调模式的机制, onBar/onTick, Tick不漏掉就不错...

    原帖地址:https://www.fmz.com/bbs-topic/1184
    在商品期货高频交易策略中, Tick行情的接收速度对策略的盈利结果有着决定性的影响,
    但市面上大多数交易框架,都是采用回调模式的机制, onBar/onTick, Tick不漏掉就不错了, 为什么呢
    因为onBar/onTick函数里面,你要处理一整遍代码逻辑,很浪费时间, 不管你愿不愿意,你的策略逻辑必须被打断,必须采用状态机的模式,比如:

    1 var state = STATE_IDLE;
    2 function onTick() {
    3   if (state == STATE_IDLE) {
    4     // do something...
    5   } else if (state == ....) {
    6     // do something
    7   }
    8 }

    FMZ没有采用这种落后的回调机制, 而是采用了不打断策略逻辑的main函数入口机制, 让用户可以更自然的控制策略流程,
    用C++与Golang做为稳定的策略底层,策略上层用Javascript/Python处理逻辑问题, 不要说脚本语言速度慢,
    除非你用它来做神经网络训练, 就算用神经网络训练, 加入Jit热编译后,他在任何场合都够用的了, Chrome秒IE十条街就是例子.
    结合事件触发机制,同样的也能使策略在第一时间最快的速度处理行情, 入门级的策略这里就不再写了, 就以期货高频Tick的合成来说,
    比如我们连接一个期货公司, 只能收到这个期货公司的行情, 我们接收行情的速度跟质量也跟自己的网络有关系,
    跟期货公司前置机的负载也有关系,那么,怎么样才能做到更快的获取更准确的期货Tick数据呢。

    在FMZ的策略模型下,你很容易就能操作N家不同期货公司的账户,并把他们的行情,融合处理,以最快的速度下单,
    正常情况下,我们最多可以从期货公司拿到两个Tick每秒, 但通过融合行情的技术,以MA801为例,我们可以拿到最多一秒6次不重复的Tick。

     

    废话不多说,直接上代码(此代码只能实盘,不能回测, 如果您不用FMZ可以只参考原理):

    实盘添加交易所时,可以添加N个期货公司,进行行情的并发融合处理. 这里暂时添加两个, 演示说明:

    function main() {
        Log("准备连接交易所并订阅行情")
        // Step 1: 全部期货前置机都开始订阅品种
        _.each(exchanges, function(e) {
            // 等待连接上交易所, 是的, 策略是 365 天不间断运行的, 休盘了也可以运行, 而且不是事件回调的逻辑
            while (!e.IO("status")) Sleep(1000);
            // 利用_C重试函数排除网络错误, 刚刚连上交易所就订阅行情, 可能会出现CTP未准备好的错误
            _C(e.SetContractType, "MA801")
            // 切换行情接收模式为立即返回模式而非事件触发模式, 可参考API文档
            e.IO("mode", 0)
        })
        Log("开始融合数据...")
        // Step 2: 重要的地方开始了
        var preVolume = 0
        while (true) {
            var ts = new Date().getTime()
            // 任何一个交易所有tick事件发生时就返回
            var ret = exchange.IO("wait_any")
            // 合适的时间重置Volume
            if (ret.Nano/1000000 - ts > 60000) {
                preVolume = 0
            }
            // 定位到发生事件的交易所
            var e = exchanges[ret.Index]
            // 获取行情, 之前切换过事件模式为立即返回, 所以这里返回的是刚更新的行情, 而且GetTicker不会失败
            // 只显示成交量递增的Tick, 实际过程,不用比较,只用处理就可以了.
            var ticker = e.GetTicker()
            if (ticker.Volume >= preVolume) {
                Log(ret, ticker.Last, ticker.Volume)
                preVolume = ticker.Volume
            }
        }
    }

    效果如下:

    可以看到21:24:44秒的时候第一个期货公司的数据比第二个先到, 添加两个期货公司就看出来效果了,如果添加5个以上期货公司一起融合
    那么你基本上没有漏Tick的可能, 如果用来开发高频交易策略,你已经解决了很重要也是决定性的一步,Tick接收的速度以及稳定可靠性.

    FMZ是专门为对策略的稳定性以及速度有挑剔级别的要求的开发者打造的一个平台. CTP低层协议技术自主研发, 可以在Linux/Windows/Mac/ARM单片机, 甚至手机下运行, 下单速度极快. 对行情反应速度快, 是做高频策略的不二之选.

    转载于:https://www.cnblogs.com/botvsing/p/10819868.html

    展开全文
  • 该项目实施了一种高频交易策略,该策略利用支持向量机来捕获 A 类和 C 类谷歌股票定价中的统计套利。 我们将演示一种交易算法,该算法以 11 的夏普比率获得丰厚的利润(2 年的回报约为 53%)。 这个想法深受以下论文...
  • 交易匹配引擎/订单簿/市场模拟器,使用3级市场数据进行高频交易策略的真实模拟。 它具有以下功能: 它实现了一个具有价格时间优先级的简单快速的现金股票订单 激进的订单与静止的流动性产生交易和消除流动性相匹配...
  • 想用python设计一个简单的基于做市商的股票高频交易策略,之前的主要class都已经写好了,现在在主程序里面实现策略,但是始终想不出一个合理的代码结构来实现,有没有哪位大神敢尝试啊哈哈: 先给出模仿的论文策略图...

    哈咯!想用python设计一个简单的基于做市商的股票高频交易策略,之前的主要class都已经写好了,现在在主程序里面实现策略,但是始终想不出一个合理的代码结构来实现,有没有哪位大神敢尝试啊哈哈:

    先给出模仿的论文策略图:
    python简单的基于做市商的股票高频交易策略

    python简单的基于做市商的股票高频交易策略

    下面是我自己能写出的主程序部分:(如果需要我写的class可以在下面评论)

    #Firstly, I load the first day's data from table BHP_data,
    #then create two lists for storing the mid price and time,
    #and then use for loop to read each events imformation, and store the mid price and time data into list.
    #afterwards, plot the first day data and time in a figure.

    import mysql.connector
    import pyodbc

    connection = mysql.connector.connect(user= 'root', password = '51jingtI', host = '127.0.0.1', database = 'HF2')
    cursor = connection.cursor()
    cursor.execute("select * from BHP_data where date='2007-07-02'")
    events_data = cursor.fetchall()

    #create two lists for storing the mid price and time,
    money = 100
    mid_price_list = []
    best_ask_price_list = []
    best_bid_price_list = []

    time_list = []
    book = OrderBook()
    book_list_bid = []
    book_list_ask = []
    profit_list = []

    for data in events_data:
    S_price = float(book.best_ask_price())+0.001
    S_PM_price = float(book.best_ask_price())-0.01
    B_PM_price = float(book.best_bid_price())+0.01
    B_price = float(book.best_bid_price())-0.001

    lo = LimitOrder(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9],data[10],data[11],data[12])
    lo_b = LimitOrder(data[0],data[1],data[2],'ENTER',B_price,1,'000','','B',0,0,0,data[12])
    lo_s = LimitOrder(data[0],data[1],data[2],'ENTER',S_price,1,'','000','A',0,0,0,data[12])
    book.add(lo)
    if book.mid_price():
        mid_price_list.append(float(book.mid_price()))
    if len(mid_price_list) > 10:
    
        if ((float(mid_price_list[len(mid_price_list)-1]) - float(mid_price_list[len(mid_price_list)-2]))>0 
            and 
            (float(mid_price_list[len(mid_price_list)-1] - mid_price_list[len(mid_price_list)-2])- 
            float(mid_price_list[len(mid_price_list)-2] - mid_price_list[len(mid_price_list)-1]))> 0
            and 
            len(book_list_bid) == 0):
    
            book.add(lo_b)
            book_list_bid.append(lo_b.get_id())
    
        elif((float(mid_price_list[len(mid_price_list)-1]) - float(mid_price_list[len(mid_price_list)-2])) < 0 
            and 
            (float(mid_price_list[len(mid_price_list)-1] - mid_price_list[len(mid_price_list)-2])- 
            float(mid_price_list[len(mid_price_list)-2] - mid_price_list[len(mid_price_list)-1])) < 0
            and
            len(book_list_ask) == 0):
    
            book.add(lo_b)
            book_list_ask.append(lo_b.get_id())
    if len(mid_price_list) > 50:     
        if not (lo_b.get_id() in book.event_dict):
            lo_b_pm = LimitOrder(data[0],data[1],data[2],'ENTER',B_PM_price,1,'','test_ask_new',data[8],1,1,1,1)
            book.add(lo_b_pm)
    
        if not (lo_s.get_id() in book.event_dict):
            lo_s_pm = LimitOrder(data[0],data[1],data[2],'ENTER',S_PM_price,1,'test_bid_new','',data[8],1,1,1,1)
            book.add(lo_s_pm)

    #instrument, date, time, record_type, price, volume,bid_id, ask_id, direction, sameoffset, oppoffset, midoffset, timestamp):

    plt.figure(figsize=(20,8))
    plt.xlabel('volume')
    plt.ylabel('Mid price')
    plt.title('Mid price of BHP')
    plt.plot(mid_price_list)
    plt.show()

    转载于:https://blog.51cto.com/6017859/2140313

    展开全文
  • 高频交易的几种策略

    万次阅读 2019-04-29 17:48:31
    西蒙斯的策略主要是利用强大的数学模型和计算机软件,在全球市场的不同产品中,进行高频交易,赚取微小的波动差,从而获取一个稳健持续的收益。这种属于市场中性策略,不太受牛市熊市的影响,只要有波动就能赚钱。...
  • 高频交易策略[z]

    2019-10-08 12:44:39
    Market Order以最高速下市价单(market order)是买方最基本的策略Looking for Price Discrepancies这个就是高频统计套利(high frequency statistical arbitrage)Indulging in Momentum Ignition人为制造价格上的spike...
  • 阅读原文:http://t.cn/RXxE6xd京东金融官方资讯QQ群:417082141 有什么想咨询的都可以来询问我们哦雷•达里奥(Ray Dalio)——对冲基金教父的人生 | 华尔街见闻在高频交易中,价格择时策略是所有投资人关注的重点。...
  • 这里尝试做了一个Tick基本准高频交易策略,只是为了实现思路。可以回测,不要直接用。。回测时候记得把回测模式改为TICK_MODE, 数据库改为TICK_DB_NAME,还有setStartDate时候initdays设为0,不需要回读历史天数,只...
  • 高频量化交易系统c++

    2019-01-16 17:26:47
    交易逻辑进行高层次抽象,将策略开发者从交易接口的底层细节中解脱出来; 可自定义C++变量的“探针”,通过“探针”可以在盘中实时可视化任何变量的走势; 策略可以将当前运行状态保存到磁盘,方便进行系统迁移; ...
  • 其中,流动性交易策略、市场微观结构交易策略、事件交易策略和统计套利策略在国外成熟市场上比较流行。 高频交易是量化投资领域,金融市场一颗璀璨的明星,是金融和科技发展的结晶。近年来高频交易的快速发展引起了...
  • 近年来,随着证券市场规模的不断扩大,金融衍生产品不断推出, 投资策略和盈利模式发生根本性改变,投资复杂程度日益提高,导致证券市场投资者的构成比例出现了相应的变化。专业投资管理人的占比越来越大,且有加速之势。...
  • 下面为你介绍一下高频交易有风险吗以及高频交易策略作步骤,如果想要了解更多高频交易方面的知识,敬请关注QR量化投资社区,下面让我们了解一下高频交易方面的知识吧! 高频交易有风险吗? 一些业界人士认为,这种...
  • 背景: 可转债作为一种金融衍生品下跌时由于具有债性保底,其债性价值一般在110-120左右。...由于可转债具备如上特性,解决了T+0,交易费率高,本金风险大的问题,其天然适合高频量化短线程序化交易
  • FX均值恢复和突破策略 基于MER(均值还原)和BO(突破)的高频交易策略
  • 高频交易,你听到这个名字有多少年了,但是你翻遍互联网,找到过真实在用的高频交易策略吗?不管别人如何, 我决定把自己使用的tick级高频交易策略分享出来。第一章:期货日内高频:普通均值回归策略1. 课程准备与...
  • 高频交易四大派系大揭秘

    万次阅读 2019-08-21 09:18:56
    所谓高频交易,简单说就是指利用计算机技术在短时间内快速进行多次买入卖出的交易行为,一般指利用微妙(1秒等于1百万微秒)为时间单位制定策略高频交易公司利用强大的电脑程序进行快速交易,交易时间经常不到十...
  • 课程内容从常用的C++开发技术讲起,到期货tick数据采集,k线生成,下单及策略撰写,从0到1实现一套可实盘的量化交易系统。 课程注重实战,学员上课后,可以达到:日常进行的数据收集,撰写量化策略,实盘交易。   ...
  • 课程注重实战,学员上课后,可以达到:日内高频交易策略研发,对统计学和概率论有一些应用上的基础,从而能够自行继续研发新的策略。将日内高频的研究发到带到短期,中期交易策略中,提高盈利机会。 课程使用数据...
  • 高频交易的思路模型简介

    千次阅读 2020-04-14 10:21:15
    高频交易凭借其巨大的获利空间,已经席卷了欧美金融市场。根据美国的Alpha杂志,2009年2月的Aite Group报告就已经指出:在美国所有交易所的交易量中,高频交易已经达到60%的份额。 根据媒体报道,光大“乌龙指”...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,495
精华内容 2,198
关键字:

高频交易策略

友情链接: prototype111.zip