股票学习网

股票学习网_股票入门基础知识_炒股入门知识 - - 股票学习网!

td指标源码(通达信td序列主图指标)

2023-04-13 21:11分类:均线 阅读:

作者 | 尔悦

采访嘉宾 | 谭雪峰

 

就在今年六月份,又一位社区 Contributor 成功入职涛思数据,他的身份也从 TDengine 的社区贡献者转变为专职的研发人员。在身份变换的同时,他对于自身的成长和发展、对于代码的品质和要求、对于开源的理解和融入都有了一个新的认知和提升。

 

你是怎么看待开源的?你觉得开源能带来什么?

如何才能成为一名优秀的 Contributor?

参与开源项目,成为 Contributor 后可以获得什么?

......

 

带着这些问题,看看他眼中的答案是否和你所见略同。

 

选择成为逆流而上的“逆行者”

 

作为大连人的谭雪峰,从小到大基本都生活在大连这座海滨城市,大学毕业后,基于自身兴趣出发便在家附近找了一份研发工作,如果没有成为 TDengine GitHub 开源社区的贡献者,或许他的生活和工作轨迹也不会这么快从大连转移到首都北京。在众多年轻人“逃离北上广”的大潮中,谭雪峰成为从家乡到北京逆流而上的“逆行者”之一。

 

 

谭雪峰

 

 

从一个熟悉的城市转移到另一个陌生的城市,这其实是一件说起来容易但做起来并不简单的事情,在这之前,95 年出生的谭雪峰可以说已经在大连扎根了 26 年,贸然间从故土抽身总会产生一些不适和纠结,但谭雪峰却并没有给自己太多的思考时间,他很快就接下了涛思数据投来的橄榄枝。

 

“虽然一直呆在大连是离家近了,工作生活会更加安逸平静,亲戚朋友之间也能有个照应,但对于研发行业来说还是北京的大环境更好。”在“苟且生活”和“诗和远方”里谭雪峰一个都没选,他选择了“未来和成长”,这是一条攀登的路,但是无疑将会看到更好的风景。

 

事实上,谭雪峰并非科班出身,他喜欢研究逆向和安全,凭借着自身的热爱他开始自学编程,毕业之后顺理成章成为了一位研发工程师。谭雪峰直言,刚开始工作时因为自己基础打的不够牢固,在工作推进时困难重重,但他并没有因此退缩,通过汲取书本上的专业知识以及参与 GitHub 上的一些开源项目,来丰富自己的专业理论和实战技能,同时这种学习方式也为他结识 TDengine 埋下了伏笔

 

“此前我是在工业物联网行业,对各种时序数据库都了解一些,以便于更好地开展工作。国产的时序数据库还是比较少的,其中能做到开源的就更少了,因此我一直都比较关注开源,在这些开源数据库里面,TDengine 的性能是非常高的,当时就想将它引入到平台系统中,这样一来二去就和涛思的人认识了。”

 

那谭雪峰为什么会加入到涛思数据?这其中还发生了哪些故事?

 

业内人都知道,涛思数据有很多学历背景强大、专业能力突出的研发工程师,他们有的来自国内外知名大学,有的是研究生、博士生,还有一些人拥有大厂研发背景,整体团队实力非常强劲。作为一个非科班出身的工程师,谭雪凭借着什么得到了涛思数据的青睐?

 

与涛思数据结缘,从开源开始

 

“我现在在涛思数据主要负责 TDengine 的应用研发和周边生态建设工作,说起来加入涛思数据的始末,除了工作上的合作加深彼此了解外,也和关注开源这件事有很直接的关系。”

 

据谭雪峰回忆,刚开始接触涛思数据其实还是因为自身工作的原因,为了完成开发任务了解了 TDengine 的源码,并为了能让其在 Windows 上使用通过 GCC 编译做了一些修改,他也因此成为 TDengine 的贡献者之一。

 

因为谭雪峰一直通过学习开源的代码来提升能力,从反哺精神出发也就想做一些事情来回馈开源社区。正好这时涛思数据举办了一场开源比赛——做 TDengine 和 HiveMQ 的对接,作为 Contributor 的谭雪峰略经思考便进行了报名,还取得了一个不错的结果。“这是我第一次参加开源社区活动,展示自己的同时还能够回馈社区,也正是通过这次活动让我更加深入地了解了涛思数据,萌生了想要加入的想法。”

 

进入涛思数据后的谭雪峰并没有给自己太多的适应时间,就立刻投入到工作中,他将整个 Go 连接器进行了重构,在此过程中对 CGO 有了更多地了解,但不可避免也遇到了一些问题。

 

“遇到比较大的问题是 CGO 的调优上面,如果 C 的方法阻塞的话会独占线程,这样一来并发性就会显著降低,当时为了解决这个性能问题我看了不少的文章,但是相关调优方法也比较少。之后在 Go 的 GitHub 开源社区上发掘了一些可以借鉴的经验,最后综合了几个渠道获取到的方案一一做 benchmark 并选了其中比较优的进行业务尝试。

 

在涛思数据工作的过程中,谭雪峰深刻感受到了如涛思这类纯技术驱动的企业技术和产品管理上的正规性,对于功能的探讨、代码的提交、review 以及质量的管理都有着非常严格的要求。由于基础软件的 bug 和性能瓶颈会直接影响所有上层应用,因此研发会更注重单元测试和 benchmark。

 

谈及到未来发展方向,谭雪峰表示还是要投身到开源项目中,从其中学习的同时贡献自己的力量推动项目发展。“目前我的工作是在为 TDengine 做周边应用,其代码也都已经开源在 Github(
https://github.com/taosdata/TDengine)上了,欢迎大家关注。”

 

开源帮助谭雪峰找到了一个前进的实现自我价值的方向。那么对于开源,谭雪峰又有哪些深刻理解呢?对于 Contributor 的成长,他又有哪些不一样的建议呢?

 

Contributor 三要素:敢写、开源精神、社区意识

 

“我认为开源是一种发展趋势,项目在开源之后会得到各个方面的反馈,使用者发现不合理的地方会提交 issue,继而社区用户会认领 issue 提交自己的修改,使用者、开发团队和社区用户三个角色共同丰富项目内容、推动项目发展,这是一个良性循环的过程。”

 

在谈到开源的价值时,谭雪峰觉得闭门造车式的项目开发势必没有开放开源力量大、速度快,俗话说众人拾柴火焰高,开源的项目成为众多开发者学习观摩的对象,反过来,开发者们也愿意用自己所学去扶持项目前进。

 

对于谭雪峰来说,他所维护的 TDengine 就是一款非常吸引开发者的开源项目,“TDengine 本身的高性能就让人眼前一亮,作为后端开发者对于性能的追求是没有止境的。”同时他认为社区维护者对于反馈的处理态度也是衡量一个开源项目优质与否的重要指标,谭雪峰回忆,在他第一次给 TDengine 提交 pr 的时候,就有专门的人联系上他进行验证和指导修改,最直观的感受就是这个社区是活的,自己提的 pr 是有价值的。

 

谈及如何成为一名优秀的 Contributor,谭雪峰认为主要在于三点。“首先是要有开源精神,参与开源就像是一个爱好一样,愿意为之付出时间和努力,再就是要敢写,提交 issue 或 pr 之后共同开发者会和你讨论提交的代码是否是合理,格式和性能是否满足,这个过程也会逐渐提高能力。最后是要有社区意识,Contributor 的头衔除了给我们个人带来荣誉外,更重要的是带来一份责任感,要发自内心地回馈社区。”

 

而且成为 Contributor 之后,开发者会更加注重代码的质量,因为这不再是只在自己的一方小世界里创造,目的仅仅是为了“跑起来”,不需要注重格式和质量,也不必太过于上心性能和调优。在开源世界里有很多人都会看到你的代码,社区将成为一种正向的鞭策力量。

 

说到自己的成长之道,谭雪峰也有一番深刻见解。“在我们进入社会之后,大部分时刻都是要靠自觉去学习和提升技能,如果在工作中缺乏自信,感觉安排下来的工作都非常困难,就更应该多看多写,不光要写代码还要把优化的过程写出来,最简单的办法就是写完一段代码之后隔半个月再去看,如果觉得当时自己写的非常 low 那就说明有成长了。”

 

“我觉得开发者最好的状态就是把自己写的代码开源出来,帮助别人的同时与开源项目一起成长。加入涛思数据后,我才是真正实现了这个‘最好’。”

 


✨想了解更多的具体细节,欢迎大家在GitHub上查看相关源代码哦。✨

作者:陈玉|涛思数据

作为一款高性能的时序数据库,TDengine提供了强大的数据分析功能。在TDengine官网()的第一个章节里,有这样的描述:“无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。”

今天,我们的主角就是上文中“可在时间轴上”聚合的强大函数——INTERVAL。

INTERVAL是TDengine一大重要功能,可以帮助我们实现降低数据采集频率的功能——也就是降采样

举个简单的例子:假设我们有某个设备一年的数据,时间数据的频率是1天,那么就是一共365条数据。现在,如果我们想按照‘月’这个频率统计,那么数据量就变成了12条。

根据官网的语法描述,相关的功能模块有三个:

  1. INTERVAL本身
  2. SLIDING
  3. INTERVAL OFFSET

对于以处理时序数据为根基的时序数据库来说,如何灵活的利用时间频率来计算分析数据实在是太重要了。下面我们围绕上面三个功能模块,分别举一个简单的应用场景的例子并做出具体说明:

 

1.INTERVAL:查询温度传感器t1记录的温度、压力每五分钟的平均值

select avg(t), avg(p) from t1 interval(5m);

这是一个最简单的使用情况,INTERVAL负责指定时间范围窗口,由AVG这种聚合函数来计算这个时间范围内的平均值。也可以换成MAX/MIN这类的选择函数,来统计出这个时间范围内的最大值/最小值。(在TAOS SQL中,聚合函数指的是COUNT/AVG/TWA/SUM等用于从数据集中汇合再计算的函数,选择函数是指
MIN/MAX/FIRST/LAST/LAST_ROW等用于从数据集中筛选结果的函数。)

INTERVAL本质上就是group by的时间版本,所以一定需要配合上述聚合或选择函数来使用。INTERVAL后面的时间单位可以是 a(毫秒)、s(秒)、m(分)、h(小时)、d(自然日)、w(周), n(自然月) 和 y(自然年)。(暂时还不支持自然周,interval(1w) 目前等效于interval(7d))。

 

2.SLIDING:可以统计类似股票市场的均线

select avg(t) from stockmarket interval(5d) sliding(1d)。

上述语句的实际含义是统计股市上某股票所有每过一天的5天的价格平均值,把这些值连起来,就是大家熟知的五日均线了。

在上述计算过程中,SLIDING起到了非常关键的作用。我们已经知道,INTERVAL 的值负责指定每次执行查询的时间窗口。SLIDING则代表着指定窗口向前滑动的时间。如下图所示:

t0s,t1s,t2s分别是三个时间窗口的起点,t0e,t1e,t2e分别是三个时间窗口的终点。当我们在查询中不指定SLIDING的值时,它默认等于INTERVAL VALUE。也即是说在第一个例子当中的select avg(t), avg(p) from t1 interval(5m)等效于select avg(t), avg(p) from t1 interval(5m) sliding (5m);

 

3.INTERVAL OFFSET:统计某个设备在其他时区(向西相差三个时区)的一个月的总数据量

select sum(t) from t1 interval(1n,3h) ;

这个SQL的语义是:统计当前服务端所在时区向西推动三个时区后的这个设备的该月总数据。OFFSET 3h代表的是OFFSET值为3h,也就是说这个SQL适用于统计不同时区的自然月数据统计。

INTERVAL OFFSET会相对复杂一些。想了解的话,需要先更多地了解INTERVAL和时区的关系。

如果INTERVAL的值是自然日(d),自然月(n),自然年(y),那么它就是对齐TDengine服务端所在时区的0点开始做的窗口切分,如下图所示:不论当前所属哪个时区,所有时间戳列的起始时间都是0点。

但是,如果是以时分秒及以下的时间单位去切分窗口,那么INTERVAL的值则是对齐从UTC-0时间的00:00:00.000开始切分的时间窗口。

如下图所示,时间戳列的起始时间都是8点,这是因为TDengine客户端的时区为UTC-8,标准时间为0点的时候,东八区为8点(注意:在POSIX标准中,UTC-8代表东八区,与平时的习惯性表达不一样)。

这个场景,就是官网文档中这段话的含义:

TDengine 中时间戳的时区总是由客户端进行处理,与服务端无关。具体来说,客户端会对 SQL 语句中的时间戳进行时区转换,转为 UTC-0时区的Unix时间戳再交由服务端进行写入和查询;在读取数据时,服务端也是采用 UTC-0时区提供的原始数据,客户端收到后再根据本地设置,把时间戳转换为本地系统所要求的时区进行显示。

总结一下就是:TDengine以时间戳形式来存储时间数据,时间戳本身是一个和时区无关的东西,但是由于TDengine要把数据查询出来展示给世界上不同地区的用户看,就和时区有关系了。在INTERVAL中,如果是自然日,自然月,自然年,均以TDengine服务端所在时区的0点为起始时间进行时间窗口区分。如果是以h(小时)及以下为单位切分窗口,那么进行窗口切分的起始时间就是UTC时区的0点。

不论是哪个时区的客户端,最终的计算列结果都是一致的,只是由于时区不同,所以显示的时候在时间戳列上会有一些偏差。因此我们强烈建议,非特殊情况下,客户端服务器和服务端服务器的时区要保持一致,从而使得两边的查询显示是一致的,从而减少不必要的误解。

比如,左侧客户端count(*)看起来应该是1 4 2,实际上却是4和3。这就是因为两边时区不一致导致的视觉差异。这时候就要以服务端的显示为准:6月30日有4条数据,7月1日有3条数据——TDengine服务端所在服务器的查询结果,永远是所见即所得的正确。

搞清楚了INTERVAL对于自然日月年和时分秒的不同切分逻辑后,接下来,我们终于可以说一下OFFSET了。

OFFSET其实是INTERVAL功能的偏移值。通过调整OFFSET值,就可以在时间轴上自由选择时间窗口的起始点。从而完成不同时区的数据分析统计。

比如,服务端当前的时区是东八区,但是我们想知道在东五区时区下,设备t1的每个月数据总量。就可以这样写:

select sum(t) from t1 interval(1n,3h) ;

但是由于OFFSET目前暂时不能支持负值,所以时间窗口的起点只能从时区东向西偏移。因此如果想用时区偏移功能统计24个时区,暂时可以把服务端所在的服务器时区设置为东十二区(UTC-12)。

作为一个定位国际化的产品,我们后面会继续完善相关的功能。如果想了解更多更具体的细节,可以在GitHub上查看相关源代码。

K线形态要求:

1、当日成交量要小于昨日成交量的1/2(即缩倍量);

2、当日阴线前一定要有大阳线,指标给的大阳是涨幅>7%;

3、当日阴线一定要回踩前面的大阳底,并且整根阴线处于大阳线的下半部。

此选股方法来源于头条大V,据说成功率高于93%。

指标用法:

1、此法选股一定要确认股价处于上升态势;

2、此选股方法一定要尾盘量价定型后再进行参与,不可于盘中选股,因为在盘中有许多不确定因素;

3、此外,用此指标选入的股票,于次日开盘低开时介入,持股时间一般不要超过三天,以一两天为宜,属于超短线投资;

4、超短线介入风险比较大,建议只以安全仓位投入。

5、股市有风险,介入需谨慎。

后附盘后用指标选出的股票,只有一支。留在此处待大家验证指标的成功率。

另外,指标中给的数值过于苛刻,

以下为指标源码,在通达信中验证通过,附在这里供大家一起研究改进。

SBL:=V<=REF(V,1)/2;

DYX:=(C-O)/O>=0.07;

TD:=BARSLAST(DYX);

ZD:=LLV(L,TD);

XG:ZD>REF(L,TD) AND SBL AND O<(REF(O,TD)+REF(C,TD))/2 AND C<O;

 

<?

/******/

//要求页面编码为 utf-8 原windows版本编码为gb2312

/******/

//1、 查询结果为多条记录的 更改方法

//原windows版本

$query = "select * from BOOK_TYPE order by TYPE_ID";

$cursor= exequery(TD::conn(),$query);

$TYPE_COUNT=0;

while($ROW=mysql_fetch_array($cursor))

{

 

$TYPE_COUNT++;

$TYPE_ID=$ROW["TYPE_ID"];

$TYPE_NAME=$ROW["TYPE_NAME"];

}

//信创版更改后的代码

$query = "select * from BOOK_TYPE order by TYPE_ID";

$TYPE_COUNT=0;

$rows =TD::DB()->prepareQuery($query);

if(is_array($rows) && !empty($rows))

{

foreach($rows as $v){

$TYPE_COUNT++;

$TYPE_ID=$v["TYPE_ID"];

$TYPE_NAME=$v["TYPE_NAME"];

}

}

/**********************************************************/

//2、查询结果为唯一一条记录

$query="select * from BOOK_TYPE where TYPE_NAME='$TYPE_NAME'";

$cursor= exequery(TD::conn(),$query);

if($ROW=mysql_fetch_array($cursor))

{

$TYPE_NAME=$ROW["TYPE_NAME"];

}

//更改后的信创版

$query="select * from BOOK_TYPE where TYPE_NAME='$TYPE_NAME'";

$row =TD::DB()->prepareQuery($query);

if(is_array($row) && !empty($row))

{

$TYPE_NAME=$row[0]["TYPE_NAME"];

}

/**********************************************************/

//3、计算查询结果的总数

//windows版本记录总数

$query="select * from BOOK_TYPE where TYPE_NAME='$TYPE_NAME'";

$cursor= exequery(TD::conn(),$query);

$num=mysql_num_rows($cursor);//总条数

//更改后的信创版

$query="select count(*) as num from BOOK_TYPE where TYPE_NAME='$TYPE_NAME'";

$row =TD::DB()->prepareQuery($query);

if(is_array($row) && !empty($row))

{

$num=$row[0]["num"];//总条数

}

/**********************************************************/

//4、insert into 创建记录额操作 高效率的办法就是保留原生的写法

//windws版本:

$query="insert into BOOK_TYPE(TYPE_NAME) values ('$TYPE_NAME')";

exequery(TD::conn(),$query);

$id=mysql_insert_id();

//信创版本:

$query="insert into BOOK_TYPE(TYPE_NAME) values ('$TYPE_NAME')";

TD::DB()->prepareQuery($query);

$id = TD::DB()->id(); //获取插入的id

//5 update 操作

$query="update BOOK_TYPE set TYPE_NAME='$TYPE_NAME' where TYPE_ID='$TYPE_ID'";

//exequery(TD::conn(),$query);

TD::DB()->prepareQuery($query);//直接更改执行方式即可

//6、delete操作

$query="delete from BOOK_TYPE where TYPE_ID='$TYPE_ID'";

//exequery(TD::conn(),$query);

TD::DB()->prepareQuery($query);// 是不是很简单 很暴力 很高效

//关于js的代码报错的解决办法

?>

<script src="<?=MYOA_JS_SERVER?>/static/js/jquery-1.10.2/jquery.min.js"></script>

<script src="<?=MYOA_JS_SERVER?>/static/js/module.js?v=<?=MYOA_SYS_VERSION?>"></script>

<!--更改为-->

<script src="/static/js/jquery-1.10.2/jquery.min.js"></script>

<script src="/static/js/module.js?v=1"></script>

<?

//8、其他说明

# top type在达梦里作为关键字 查询时候带有这种字段注意转义 \"top\" 这样写就好

# 所有user表的名称注意改为TD_USER

# 很多错误在日志里看不出来,找不到问题就恢复重改

# 本地改完后直接拖进去,不要在线改,会掉线

# 如有其它技巧继续补充 及时共享

# 1000-01-01 00:00:00

/****/

#重启达梦数据库的操作

#1 cd /opt/dmdbms/script/root/

#2 systemctl status DmServiceDMSERVER.service

#3 systemctl stop DmServiceDMSERVER.service

#4 systemctl start DmServiceDMSERVER.service

?>

https://www.haobaiyou.com

上一篇:600729股票分红方案(股票行情)

下一篇:竞价星(竞价广告)

相关推荐

返回顶部