构建区块链量化交易系统(一)

Yaser Abu-Mostafa在公开课说工程师,喝着咖啡等待机器运算出合理的结果,然后就完成了任务,坐等顾客付钱,这也是我写这篇文章以及代码的原因。

本文结构,暂时分为,三个部分

一,基础理论以及代码基础

二,机器学习在上的基础应用(Tensorflow + Python去做)

三,系统可靠性加固

代码在https://github.com/hzm1313/yc,代码冗余了其他一些东西,后面会用JAVA9的模块特性把模块给分出来,火币网的接口封装了WS,和restful,杠杆未封装

平台选择为火币网,说起来是因为以前火币网不用翻墙,可惜现在也要翻了,所以翻墙是必备的,可以用SSTAP去连接SSR结点,会将TCP,UDP连接也进行转发,原生的用IDEA调试总是有问题

点击我去搭建SSR  SSTAP下载链接,已经不维护了,可以自己选其他的

量化交易定义

根据深圳交易所对量化交易的研究可知,量化交易是指投资者利用计算机技术、金融工程建模等手段将自己的金融操作方式,用很明确的方式去定义和描述,用以协助投资者进行投资决策,并且严格的按照所设定的规则去执行交易策略(买、卖)的交易方式。按照数学模型的理念和对计算机技术的利用方式,量化交易方式可以进一步细分为自动化交易(Automatic Trading)、数量化投资(Quantitative Investment)、程序化交易(Program Trading)、算法交易(Algorithm Trading)、以及高频交易(High Frequency Trading)

自动化交易

指将技术分析投资方式固化成计算机可以理解的模型、技术指标,计算机程序根据市场变化自动生成投资决策并付诸执行的交易方式。简而言之,自动化交易是技术分析投资方式的自动化。自动化交易可以避免投资人的心理变化和情绪波动,严格执行既定策略,是最基本的量化交易方式,在外汇交易和期货交易领域应用很广。

程序化交易

是从美国七十年代的证券市场上的系统化交易发展演变而来的,是伴随着股指期货与现货市场套利交易而兴起的数量化交易方式。纽约证券交易所(NYSE)把程序化交易定义为:Program trading encompasses a wide range of portfolio-trading strategies involving the purchase or sale of a basket of at least 15 stocks with a total value of $1 million or more.即任何含有标普500指数15只股票以上,其价值100万美元以上的交易,属于程序化交易。纽约证券交易所的定义主要突出的是交易规模和集中性。程序化交易发展到今天,其含义已经远远超过了纽约证券交易所当初的定义。国泰君安证券对程序化交易给出了一个更为市场化的定义:根据一定的交易规模和规则生成买卖信号,由计算机自动执行买卖指令的交易过程。简单的说,就是利用计算机程序来控制买进卖出的事迹并自动执行。在这个定义中,突出的是交易模型、计算机程序对交易的重要性。随着量化技术的深入发展,程序化交易和算法交易的界限逐渐模糊,有些市场使用高频交易描述流行的量化交易方式。

高频交易

源于程序化交易和做市商机制,是指透过极高速的超级电脑分析高频交易数据中的价格变化模式,并且利用这些价格变化模式获利,通常高频交易利用服务器的地理位置优势(Co-location),在相对更快的时间内获得市场行情和执行大量交易指令,从而取得普通交易方式难以获得的利润空间。近年来,除了信息技术是的交易速度不断加快之外,交易平台日趋多元化也使得高频交易成为可能。

数量化交易

通过研究基本面去做,做爬虫爬信息去做

算法交易

更好的价格买入,因为你作为资金量较大的用户,买入,市场印象较大

算法交易,数量化交易(研究基本面)我研究不多,因为概念上对于大多数人并不是一个很优秀的实施概念,所以就不展开了,要是有什么好的文章或者思路也可以分享给我,感谢

自动化交易,高频交易,程序化交易是在本系统构建范围之内

代码构建思路

现在我写了2个策略

策略A,1分钟线上下跌30次,买入,上涨或者下跌0.005%卖出

策略B,网格策略,上涨5%,10%,15%,分别买入总价的30%,30%,40%,下跌反之,基准价,我开上帝模式,选了要给比较好的基准价

这是自动化交易

策略A进一步,1分钟下跌(N)次,选择一个比较优秀的下跌次数以及回测范围,去回测,动态的生成策略

策略B进一步,网格策略,上涨N%,买入总量/当前量的N%,去回测,动态生成优秀的策略

高频交易

比如说现在币安,火币网,币安下跌,火币网上涨,这个时候我拥有火币网的币,是否卖出,当然卖,为什么?因为根据历史回测来看,币安作为全球第二的市场,反应币火币网快。也可以参考CEX,这种可以对冲的市场,现在有自动搬砖的软件了,我也就重点实现了

火币网API,实现有RESTFUL,和websocket2种类型,websocket接口有行情接口,restful接口有行情和交易接口,但是restful行情接口有不好的地方,速度和历史数据没有websocket的久远

基于上面2个策略,我做了回测,效果都不是很好,因为现在我选取之前的时间段是单边下跌时间,所以回测结果基本上都是亏损,下面是代码代码放在我的GIT

 @Test
    public void baseStrategy() {
        //策略1
        //连续下跌30分钟线,买入,直到,高于成本价0.5%,卖出,否则一直持有,手续费为0.4%,如果下跌超过1%,,无条件卖出
        //读取数据
       /* List<HuobiDetailVO> huobiDetailVOList  = HuoBiApiUtils.importToFile("E:\\虚拟货币\\测试数据\\test_1min.xlsx");*/
        List<List<String>> lists = ExceUtil.importFile(new File("E:\\虚拟货币\\测试数据\\test.xlsx"));
        if (false) {
            List<Map<String, String>> mapList = new ArrayList<>();
            for (int fallTraigger = 1; fallTraigger < 30; fallTraigger++) {
                //1W刀本金
                BigDecimal amount = new BigDecimal("10000");
                BigDecimal holdPrice = new BigDecimal("0");
                BigDecimal holdNum = new BigDecimal("0");
                BigDecimal basePrice = new BigDecimal(lists.get(1).get(3));
                BigDecimal open = new BigDecimal(lists.get(1).get(2));
                BigDecimal close = new BigDecimal(lists.get(1).get(3));
                BigDecimal high = new BigDecimal(lists.get(1).get(4));
                BigDecimal low = new BigDecimal(lists.get(1).get(5));
                //触发的卖出价格
                BigDecimal sellLowPrice = new BigDecimal(lists.get(1).get(3)).multiply(new BigDecimal("0.99"));
                BigDecimal sellHighPrice = new BigDecimal(lists.get(1).get(3)).multiply(new BigDecimal("1.005"));
                int falNum = 0;
                for (int i = 2; i < lists.size(); i++) {
                    open = new BigDecimal(lists.get(i).get(2));
                    close = new BigDecimal(lists.get(i).get(3));
                    high = new BigDecimal(lists.get(i).get(4));
                    low = new BigDecimal(lists.get(i).get(5));
                    if (holdNum.compareTo(new BigDecimal("0")) == 0) {
                        //持有本金,买入等待状态
                        if (close.compareTo(basePrice) < 0) {
                            falNum++;
                        } else {
                            falNum = 0;
                        }
                        if (falNum >= fallTraigger) {
                            //买入手续费
                            amount = amount.multiply(new BigDecimal("0.998"));
                            holdPrice = close;
                            holdNum = amount.divide(holdPrice, 10, BigDecimal.ROUND_DOWN);
                            amount = new BigDecimal("0");
                            //System.out.println("买入价:" + holdPrice + " 买入数量:" + holdNum + " 总价值:" + holdNum.multiply(holdPrice) + " 剩余钱:" + amount.toString());
                            sellLowPrice = new BigDecimal(lists.get(i).get(3)).multiply(new BigDecimal("0.994"));
                            sellHighPrice = new BigDecimal(lists.get(i).get(3)).multiply(new BigDecimal("1.006"));
                            falNum = 0;
                        }
                    } else {
                        //持有币,卖出等待状态\
                        //低于1.05卖出
                        if (close.compareTo(sellLowPrice) < 0 || close.compareTo(sellHighPrice) > 0) {
                            holdPrice = close;
                            amount = holdNum.multiply(holdPrice).multiply(new BigDecimal("0.998"));
                            //System.out.println("卖出价:" + holdPrice + " 买出数量:" + holdNum +" 税后钱:"+amount);
                            holdNum = new BigDecimal("0");
                        }
                    }
                    basePrice = close;
                }
                if (holdNum.compareTo(new BigDecimal("0")) > 0) {
                    //强行卖出
                    amount = holdNum.multiply(holdPrice).multiply(new BigDecimal("0.998"));
                }
                System.out.println("fallTraigger:" + fallTraigger + "  resultPrice:" + amount.toString());
                Map map = new HashMap<String, String>();
                map.put("fallTraigger", fallTraigger);
                map.put("resultPrice", amount.toString());
                mapList.add(map);
            }
            mapList.sort((o1, o2) -> o1.get("resultPrice").compareTo(o1.get("resultPrice")));
            mapList.forEach(obj -> {
                System.out.println(String.valueOf(obj.get("fallTraigger")) + "===" + obj.get("resultPrice"));
            });
        }
        //策略2,网格策略
        //为了拿一个好看的回测结果,我就上帝模式来一波,数据是自己去取的一个平均值
        //步长5%,上涨5%,卖出30%,上涨10%,卖出30%,上涨15%,卖出40%,
        //下跌同理,简化了很多东西
        for(int stepType=1;stepType<4;stepType++){
            BigDecimal stepLength = new BigDecimal("0.5").multiply(new BigDecimal(stepType));
            BigDecimal basePrice = new BigDecimal("8000.5243315970");
            //1W刀本金
            BigDecimal amount = new BigDecimal("10000");
            BigDecimal holdNum = new BigDecimal("0");
            BigDecimal tradePrice = new BigDecimal("0");
            BigDecimal close = new BigDecimal(lists.get(1).get(3));
            BigDecimal percent3 = new BigDecimal("0.30");
            BigDecimal percent4 = new BigDecimal("0.40");
            BigDecimal opPrice =  null;
            ReseauStratge trade[] = {new ReseauStratge(amount.multiply(percent3)),new ReseauStratge(amount.multiply(percent3)),new ReseauStratge(amount.multiply(percent4))};
            for (int perIndex = 2; perIndex < lists.size(); perIndex++) {
                close = new BigDecimal(lists.get(perIndex).get(3));
                //买入/卖出
                //对于每个阶段的资金来说,只有,买入,卖出2种状态
                for(int buyPercentNum=0;buyPercentNum<trade.length;buyPercentNum++){
                    opPrice = new BigDecimal(basePrice.toString());
                    BigDecimal step = new BigDecimal("1.00");
                    if(trade[buyPercentNum].getCanBuy()) {
                        //买入
                        for(int muNum = 1; muNum<=buyPercentNum+1;muNum++){
                            step = step.divide(stepLength,10,BigDecimal.ROUND_FLOOR);
                        }
                        opPrice = opPrice.multiply(step);
                        if(close.compareTo(opPrice)<=0) {
                            trade[buyPercentNum].setTradePrice(close);
                            trade[buyPercentNum].setTradeNum(new BigDecimal(trade[buyPercentNum].getHoldAmount().divide(close,10,BigDecimal.ROUND_FLOOR).toString()));
                            trade[buyPercentNum].setHoldNum(trade[buyPercentNum].getTradeNum());
                            trade[buyPercentNum].setTradeAmount(trade[buyPercentNum].getTradeNum().multiply(trade[buyPercentNum].getTradePrice()));
                            trade[buyPercentNum].setHoldAmount(trade[buyPercentNum].getHoldAmount().subtract(trade[buyPercentNum].getTradeAmount()));
                            trade[buyPercentNum].setCanBuy(false);
                            holdNum = holdNum.add(trade[buyPercentNum].getHoldNum());
                            amount = amount.subtract(trade[buyPercentNum].getTradeAmount());
                           // System.out.println("买入"+"holdNum:" + holdNum + "  resultPrice:" + amount.toString()+"总价值" + amount.add(holdNum.multiply(close)));
                        }
                    } else {
                        //卖出
                        for(int muNum = 1; muNum<=buyPercentNum+1;muNum++){
                            step = step.subtract(stepLength);
                        }
                        opPrice = opPrice.multiply(step);
                        if(close.compareTo(opPrice) >= 0) {
                            trade[buyPercentNum].setTradePrice(close);
                            trade[buyPercentNum].setTradeAmount(trade[buyPercentNum].getHoldNum().multiply(trade[buyPercentNum].getTradePrice()));
                            trade[buyPercentNum].setHoldAmount(trade[buyPercentNum].getHoldAmount().add(trade[buyPercentNum].getTradeAmount()));
                            trade[buyPercentNum].setTradeNum(trade[buyPercentNum].getHoldNum());
                            trade[buyPercentNum].setHoldNum(new BigDecimal("0"));
                            trade[buyPercentNum].setCanBuy(true);
                            amount = amount.add(trade[buyPercentNum].getTradeAmount());
                            holdNum = holdNum.subtract(trade[buyPercentNum].getTradeNum());
                          //  System.out.println("卖出"+"holdNum:" + holdNum + "  resultPrice:" + amount.toString()+"总价值" + amount.add(holdNum.multiply(close)));
                        }
                    }
                }
            }
            System.out.println("holdNum:" + holdNum + "  resultPrice:" + amount.toString() +"总价值" + amount.add(holdNum.multiply(close)));
        }
    }

这就是交易的基础模型,价值还是有价值的,毕竟还是挣钱的,挣的特别少,1W刀,100刀-700刀,幅度太坑,2个月的回测,17年12月到18年的2月

holdNum:0E-10  resultPrice:10746.2908951017280000000000000000总价值10746.2908951017280000000000000000
holdNum:0E-10  resultPrice:10548.5590028459460000000000000000总价值10548.5590028459460000000000000000

holdNum:0E-10  resultPrice:10139.7957370829220000000000000000总价值10139.7957370829220000000000000000

能不能挣钱,就看steplength以及basePrice的设置

现在是定死的价格,所以如果做无限动态的化,可以考虑每天/每小时/重新设置basePrice,看自己的需求

这是2种基础的交易模型

然后这个时候需要引出风控了,因为在回测的时候,模型成功率在某段时间不高的时候,所以需要终止模型的运转,发出邮件通知自己

高频交易

(BitMex/Biance)与火币做对比

----代码暂时未写,不想爬虫,不想封接口了,都TM苦力活,要吐了,后面补进来---

交易模型已经构造完毕

交易系统,稳定,快速,易更改,可监控(其实redis一套可以弄完,不过是为了学习,会采取自己接触比较少的东西去做)

监控选用 Promethus,然后拉取数据,做可视化

稳定:代码看自己了

快速:并发的走起

更改:数据库配置的走起,然后RabbitMQ做消息队列推

存储: redis持久化搞

现在很多海外服务,所以用spring cloud,搭建微服务,做服务调用

java + python交互,做机器学习模型结果的交互

这是我整个系统的构造思路,代码会在git里面也会一步一步OVER掉所有需求

猜你喜欢

转载自blog.csdn.net/shzm0/article/details/79860546