文章分类 » 技术

股票软件脚本的几个函数

自己炒股,之前发现一个指标,觉得挺有使用价值的,想要自己通过这个指标选股。

一开始的想法,是自己写代码解析同花顺、东方财富之类的软件的数据,因为本科时候自己的一个小项目就是解析这些软件数据的,应该好弄。但是后来在做公式和指标的时候发现,有很多的公式,应该是软件本身就有的,比如均价,最低价、最高价,指数平滑移动均价,等等。

这些指标自己再去实现,首先自己做不一定能一次做对,其次哪怕做对了,可能中间也要花费大量的时间,最后,我是知道这些软件都是能编辑指标、公式的,这些东西自己再去实现一遍实在是有些没必要。

于是,根据自己发现的那个指标,来研读软件的这些系统自带公式,整理了一些用得到的指标,后续的选股方法也放在软件上去实现,而不是非得要自己写代码了。当然当前这种情况自己也没避免写代码,只是写的代码只是应用方面了。

函数:

HHV:求最高值,HHV(X,N)=>表示N个周期内X的最高值,X可以是其他的指标,比如HH:HHV(H,60)=>表示60个周期内最高价的最高值,以日线为例则表示60日内最高价

LLV:求最低值。HHV的反向函数,用法相同。

OPEN:开盘价(同O)

CLOSE:周期收盘价(同C)

LOW:周期最低价(同L)

HIGH:周期最高价(同H)

VOL:成交量(手),(同V)

AMOUNT:成交额(元),(同AMO)

以下几个复杂函数释义参考:https://zhuanlan.zhihu.com/p/584492746

MA:简单移动均价,简单算数平均值,不分轻重,平均算,N日内收盘价均价(当前周期使用当前价格)

EMA:指数平滑移动平均,EMA(C,N)=2*C/(N+1)+(N-1)/(N+1)*昨天的指数收盘平均值,在计算时,考虑了前一日的平均值,平滑系数固定。

SMA:SMA(C,N,M)与EMA的区别就是增加了权重参数M,也就是用M代替EMA平滑系数中的2,这样我们可以根据需要调整当日数值在均价中的权重=M/N。(要求N>M)

DMA:DMA(C,A) 中A为权重值,公式如下:X=DMA(C,A)=A*X+(1-A)*X'(A小于1),可以发现,DMA与SMA原理是一至的,只是用一个小数直接代替了M/N;而在实用中,这个小数最有价值的就是换手率=V/CAPITAL;DMA(C,V/CAPITAL)的直接含义是用换手率作为权重系数,利用当日收盘价在均价中的比重计算均价;直观理解就是换手率越大,当日收盘价在均价中的作用越大。

REF:引用几个周期之前的数据,REF(O,1)->调用前一天的开盘价

CROSS:穿越,CROSS(A1,A2),指标A1超过A2

此外搬运一个耿直老哥的选股方法:

同花顺问财选股里输入:DDE连续3日净流入,实际流通盘小于50亿,月换手率排行,平台整理。

大概能选出二三十个,删掉近期大涨的,删掉日成交额低于5000万的,大概还能剩下10个,然后取月换手率排名前6的,找个筛子,扔出几就买哪个。

mysql使用问题

前几天采集数据折腾着玩,在服务器上卸载了原来的marialdb,重新安装了新版本的mysql,创建数据库,创建账户,授权,然后本地连接、本地跑数,都挺正常。

程序写好之后,代码在本地跑的效率就不乐观,觉得可能是网络的问题,放到服务器上可能会好一些。把代码放服务器上去跑,发现性能有所提升,但是还是不太对,不应该是本地跑数的速度。

看了一下阿里云的后台监控,发现还有内网消耗,忽然想起来,上传代码的时候,代码里写的数据库连接还是IP地址,不是127.0.0.1或者localhost,导致还是走了部分网络。

重新修改配置,打包代码发布到服务器上,启动。访问首页,结果报错,异常信息:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Public Key Retrieval is not allowed,之前没遇到过,但是根据当时自己建库的过程,盲猜是用户配置的问题,当时给用户配置的host是%。

搜索一下网络,发现大家给的解决方案是:

在数据库连接url的后边加上参数: allowPublicKeyRetrieval=true

原因是:如果用户使用了 sha256_password 认证,密码在传输过程中必须使用 TLS 协议保护,但是如果 RSA 公钥不可用,可以使用服务器提供的公钥;可以在连接中通过 ServerRSAPublicKeyFile 指定服务器的 RSA 公钥,或者AllowPublicKeyRetrieval=True参数以允许客户端从服务器获取公钥;但是需要注意的是 AllowPublicKeyRetrieval=True可能会导致恶意的代理通过中间人攻击(MITM)获取到明文密码,所以默认是关闭的,必须显式开启

最终改成:

jdbc:mysql://127.0.0.1:3306/lottery_probability?useSSL=false&allowPublicKeyRetrieval=true

再发布,启动,OK,并且执行速度提升了好几倍,这才是应该有的速度。不过即使这样,也需要跑几个小时。。。等着吧

爬虫爬取某菠菜网站的结果

查看网站,结果在外边没有,需要用正式用户或者游客身份登录之后才能拿到
登录之后,查看请求内容,发现只有一个get的请求是主要数据,但是整个是页面,不是单独的数据
摘出来链接:/member/dresult?lottery=AULUCKY5&date=*&table=1
写爬虫的时候需要替换这里的日期

用熟悉的语言,java写,因为后续还需要做成服务,做服务的时候,java也比较顺畅

使用原来写的httpUtil爬取,发现从网站拿来的header有的不能用,搜了一下,是http2里可以自定义的key,比如key使用冒号开头
// :method: GET
// :path: /member/dresult?lottery=AULUCKY5&table=1&date=2018-01-01
使用java自带的http请求会无法携带这些自定义的header
查资料,发现jdk8处理http2略微有些麻烦,直接使用支持http2的jdk版本比较方便。到oracle上去下载。下载了16.

下载成功之后,安装,整个环境的参数已经被修改,执行java -version 显示是jdk16了。

使用开发工具idea增加仓库,发现总是报无法识别的仓库地址。想了一下,好像是因为我idea比较老的原因。。。我的idea还是2017版的。。。

没办法,这个方法得放弃了。使用另外一种方式。

修改项目依赖,增加依赖okhttp3,当前环境使用的是jdk8,直接在仓库里找了个比较新的版本

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.1</version>
</dependency>


结果依赖的包怎么都引入不进来,根本没法实例化。
弄了半天仍然不行,忽然想到可能也是版本的原因。

去查了一下这个版本包发布的时间,确实是在jdk8之后很久,时间差距有点太大,可能是这个原因,切换一个比较老的版本试试。

找了个距离jdk8发布时间比较接近的版本,

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.11.0</version>
</dependency>


修改这个配置之后,OK了,可以实例化了。
写个公用点的方法,可以动态添加header

public static String getUrlContent(String urlStr, Map<String, String> headers) {
try {
Request.Builder requestBuilder = new Request.Builder().url(urlStr);
headers.forEach(requestBuilder::addHeader);
Request request = requestBuilder.build();
Response response = client.newCall(request).execute();
if (Objects.isNull(response)) {
throw new IOException("Response is null");
}
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
if (Objects.isNull(response.body())) {
throw new IOException("Response body is null");
}
return response.body().string();
}
catch (IOException io) {
System.out.println("获取URL资源异常!,URL :" + urlStr);
throw new RuntimeException("获取URL资源异常!URL " + urlStr);
}
}

把从浏览器里扒出来的header都写到代码里,然后写死一个地址,尝试请求一下
/member/dresult?lottery=AULUCKY5&date=2018-01-01&table=1

请求成功,但是显示的是乱码。从网上找资料,有的说把gzip这个header的这一项去掉,试试。

尝试成功,打印出来了需要的页面内容。

按照之前跟大佬交流时候的提议,建议在爬完一些网页之后,为了避免需要重新摘取里面的数据的时候,网页出现了变化,需要重新解析,所以第一次爬完之后就把所有的爬取下来的网页直接保存成文件,后续需要用的时候,直接拿这些文件用就行了,不需要再重新去爬取,还需要处理各种外部变化问题。

不过这次应对的网站比较简单,感觉不会有这么频繁的变化,先把数据爬下来再说。写入文件也就一步简单的操作,先写数据解析的部分。