初入A股市场

最近A股市场火爆,股指连续创新高,我也不能免俗的入市了。这并不是我第一次涉足A股。第一次是去年大约10月份的时候,在朋友的鼓动下,开了一个证券账户。当时沪指大约2400点左右,大家都在议论着,牛市要来了。当时看了下沪指的周K线,确实有开始上涨了趋势。但后面上涨的速度和幅度,都大大超出了我的预期。

开通A股账户后,只是抱着玩玩的心态,充了1W进去。当时看雪球上很多人推荐银行股,就买了一只银行股,还有几只其他的股票,都是成份股。拿了几天之后,市场几乎没有任何波动,觉得每天自己不断的看行情挺傻的。1W块钱也没啥值得自己耗费精力的,就全部提现了出来。

又过了大约一个月后,市场再次开始上行。经过我认真的考虑,觉得A股还是有投资机会的。但又不想太麻烦的选股,所以准备开始基金定投计划:计划分十次,每周1次买入5000块钱的大盘基金。因为自认为自己能承受的风险水平比较高,所以选择了分级基金银华锐进。这个基金也是朋友推荐的,本着了解自己投资对象的原则,我认真的研究了分级基金的运作原理,然后开始了买入。当时沪指大约2500点左右。然后,市场开始爆发了,我觉得这种行情下定投有点傻,在2600点的时候,就一次性投入了全部剩余的80%资金。接下来的暴涨大家都知道了,但我实际上没赚到多少,2800点的暴跌的时候,把我甩下去了。接下来,我只能每天的看着市场不断上扬,不敢再追高了。这次大约赚了20%。

我知道市场不会一直单边上涨,准备在A股阶段性的调整后再次入市。所以,在上周沪指创新高的时候,我再次入市了。这一次,我自己出了部分,另外以收益提成的方式从朋友那募了部分资金,总共10W,准备认真的去做。

然而,出师不利。为了防止系统性风险,我给自己定了一个规则,同时持有不超过三只股票,每只股票不能超过总资金的三分之一。所以上周自己选了三只股票,分别是中信证券、交通银行和中国人寿。前两只已经开始了向上的趋势了,所以买入。中国人寿还处于震荡整理中,准备等到向上突破后买入。然而,市场喜欢开玩笑,上周中国人寿来了一次假突破,我全仓追入了。另外,我还坏了自己另外一个规矩,买了一只别人推荐的股票。我的投机经历告诉我,盲目的听信别人总是要吃大亏的。这只股票是中国南车,刚刚创了新高。于是,我再次在最高点追入了。总结下来,这两次追高操作产生的亏损抵消掉了另外两只股票的大部分盈利。在过去几天大盘调整的时候,我剩下的利润也失去了。为了保住本金,所以,我选择了清仓。

当然,你可能会说,这几只股票再多拿几天就会没事了。我也相信这几只股票都是不错的股票,但不能因为这个打破自己的规则,一错再错。两只下跌的股票已经到了我的止损线了,另外,我不允许自己本来盈利的交易变成亏损状态。

总结了一下这次交易,失败的主要原因主要有:1、追高操作,没有买在安全点;2、全仓进出,风险过大;3、听信消息;4、同时持有股票数太多。这次交易也给自己一个教训,A股虽然是牛市,但也很凶险,赚钱没那么容易,不能太过于轻心了。

经过过去一段时间的看盘,加上自己之前的投机经验,所以针对A股给自己制定了一个交易系统。

仓位:
同时最多持有2只股票,单只股票最高不超过50%资金。

买入原则:
1、日K线的 MA5 在 MA20 上方。
2、60分钟K线的 MA5 刚刚向上穿越 MA20 时,买入

买入方法:
分三次买入,分别是 4:3:3 ,后面的买入价位必须比上次买入价位要高。

止损:
单笔交易损失不能超过总资金的1%。所以,根据上面的几个原则,买入一只股票后的止损线为5%。另外,在有一定的盈利的时候,根据情况,逐步调高止损线,确保本金和部分利润不能损失。

卖出原则:
和买入原则相反,60分钟K线的 MA5 向下穿越 MA20时,卖出。然后换股,不参与盘整。

另外,选股的问题,A股几千只股票,现在还不熟悉,所以暂时只从沪深300指数的成份股里面选股。

这套系统是我在其它市场经过长时间的摸索,制定出来的,并且经过了一段时间的考验,收益不错。根据A股市场的特点,修改了一些参数。这套系统最大的特点就是以追踪短期趋势为目的,其买入,止损,卖出都是客观可量化的,尽可能避免人性的因素而影响决策。

然而,我深知,除非是计算机,再有效的系统也很难避免人性的因素,遵守纪律是最重要的事情,这一点,我做的还不够好。

比特币及其产业链

谈到比特币,很多人的第一反应是:这东西不是被禁止了吗?或许很多人对比特币的了解还停留在13年底比特币的火爆及央行对其的打压的时候。事实上,经过2014年一年的发展,虽然比特币的价格一路下滑,但比特币生态环境却发生了天翻地覆的变化,从一个流行于极客圈的的玩物,俨然发展出了成熟的产业链。从挖矿到交易到支付,以及丰富的比特币衍生品,比特币正从幼稚走向成熟。

什么是比特币

比特币系统是一个相对复杂的系统,即使对于程序员而言,要想完全的理解它的运作方式也非易事。事实上,就连李笑来这种自称非常了解比特币的人,在其公开的微博上,也搞不清楚公钥是什么东西。我本人也是花了很久的时间才彻底搞清楚比特币系统里面的各种概念。想要理解比特币的工作原理,首先要读的就是 Satoshi Nakamoto 的白皮书:Bitcoin: A Peer-to-Peer Electronic Cash System. 里面的概念可能需要多读几遍才能读懂。另一个值得去得地方是比特币的 Wiki. 对于比特币相关的开发者,官方的文档是必须要读的。

但是,对于一般人来说,要使用比特币,并不需要完全的理解它的运作原理,只需了解比特币的特征,知道几个基本概念即可。

比特币是基于互联网的加密电子货币,可以把它理解为电子黄金。它具有很多黄金的属性,并且从某些角度来看,比特币更具有优势。

首先,它总量固定为2100万枚。它通过一种称为挖矿的形式来发行新的货币,它的产量会大约每隔4年减半,最终达到一个最大值,目前已经产出了不到1400万枚。虽然从长期看来,它使一种通缩型货币,但目前,它仍然处于早期的发行阶段,是严重的通胀型货币。

其次,它是一种去中心化的系统。和传统的金融体系不同,比特币没有一个中央节点来控制它的运作和发行,而是所有的节点通过特定的协议和规则达成的共识。这有两个意义,一个是没有人能够(或者说很难)控制这个系统,比如增发货币,撤销某一笔交易,修改规则等等;另一个是它无法被完全的禁止,因为无法做到关闭某一个主机就能关闭整个系统,只要互联网存在,它就能够存在。所有,有人称它为有史以来最危险的开源项目。

另外,比特币是匿名的。比特币是通过比特币地址来保存比特币。一个比特币地址是类似这样的:13dUm4aNZQDNQpwnX1PxaBQfUdjnFwbba1 这完全是通过随机算法生成的。每个地址对应有私钥,只要拥有了私钥,便拥有了该地址对应的比特币。有意思的是,所有的交易信息在比特币系统里面都是公开的,每个完整的节点都保存有史以来所有的交易记录,但人们并不知道某一个地址是谁所拥有。由于它的匿名,使得它被用于一些非法的活动,比如卖卖枪支毒品,黑客勒索,藏匿财产等,但这并不是比特币的原罪,它只是一个工具而已。不过由于现在不管是国内还是国外的交易所,买卖比特币都需要经过实名认证,所以给追踪比特币交易带来了一些可能。

比特币产业链

挖矿

目前,比特币每天产出的数额大约为3600枚。即使按照目前的币价,每天的产出额也将近100万美元。

根据比特币发行的原理,运行哈希运算的速度越快,获得比特币的概率就越高。而比特币每天产出的数量是有限的,所以比特币挖矿是一场残酷的军备竞赛。比特币挖矿设备经历了四个阶段,每一阶段都比上一阶段的效率提升数个数量级。第一个阶段就是在比特币刚诞生后的几年内,用普通的 PC 即可参与比特币挖矿,这为 CPU 阶段。当比特币开始交易产生价值时,人们发现用显卡挖矿效率更高,这进入了第二个阶段,为 GPU 阶段。然后是 FPGA (现场可编程逻辑门阵列)阶段。目前为 ASIC (专用集成电路)阶段。随着军备竞赛的升级,全网算力越来越高,这也给比特币网络提供了更大的安全性。

比特币全网算力走势

图为过去一年比特币全网算力的变化曲线,一年之内增加了超过10倍。增长这么快一个是因为设备效率的提升,另一个是参与人数的增加。目前比特币全网算力为350P左右,这是什么概念呢,这相当于有35W台最新型的矿机24小时不停的运算。而且,这些矿机只能用来挖矿,不能用作其他用途。容纳上万台比特币矿机的矿场在全球都屡见不鲜。

比特币挖矿曾经是一个暴力的行业。最早的 ASIC 芯片问世时,买入者在很短时间内便能挖回买入矿机的钱,再加上币价的大幅上涨,获得了惊人的回报。那些早期投资烤猫股票的人,更是获得了上千倍的回报。

然而,过去的一年,由于币价的下跌,大量矿机挖出的比特币不够支付电费,投资者血本无归。矿机生产商面临行业洗牌,去年出现的很多矿机商已经倒闭,目前剩下蚂蚁矿机一家独大。

交易

从某种程度上说,比特币算是最完美的投机品了:涨跌幅巨大,不收手续费,7*24不间断交易,没有T+1限制,不需要繁琐的开户门槛,交割极为方便。交易是比特币目前最主要的应用,未来也会继续如此。通过交易,比特币实现了价值的发现,也为其他应用带来的基础。

我第一次想购买比特币时,国内几乎没有看起来正规的交易所,所以没有敢买入。而现在,国内目前至少十几家比特币交易所,国际上也出现了很多。国内最大的有三家交易所,分别是 比特币中国,okcoin 和 火币。由于残酷的市场竞争,国内交易所纷纷放弃收取交易手续费,并且推出支持自动化交易的 API、手机客户端等产品,从体验上完胜传统的券商。这体现出了互联网金融的巨大威力。

比特币价格在过去几年最大涨幅数千倍,带来了巨大的投资机会,很多早期入场者因此获得了巨额的收益,然而更多人在残酷的市场里面血本无归。参与比特币市场交易的人有很多种,有长期看好比特币不断买入持有的,有旷工卖出比特币套现的,也有大量的短线投机者,还有拥有大量资金能够影响比特币价格的人也就是人们俗称的庄家。

过去的一年,由于比特币价格的持续下滑,人们发现做空更容易赚钱。于是出现了融资融币,出现了期货。特比是期货,由于具有高达20倍的杠杆,使得本来就涨跌幅巨大的比特币变得更加危险,比特币交易变相的成为了赌场。庄家也更容易的坐庄了,因为比特币盘子本来就很小,庄家通过期货建仓,现货拉盘或砸盘,在短时间内吃个来回。散户做期货运气好能赚个几倍,但终究是要还回去的。

支付

比特币另外一个重要的应用为支付。和传统支付手段相比,比特币有更低廉的手续费,更快的速度,以及能够匿名支付。我有过几次使用比特币在网上购买 VPS, VPN, SSL 等服务的经历,整个流程非常流畅,不需要提交复杂的个人信息和信用卡信息,也不用担心信息泄露的可能。

在跨境支付上面,比特币有天然的优势。因为比特币是基于互联网的,是没有国界的。没有比特币的话,只能通过银行转账或信用卡支付。然而,银行转账流程特别复杂,周期也很长。信用卡比较方便但门槛较高,很多人比如大学生是没有信用卡的。对于有外汇管制的中国,使用比特币也能够突破这一限制。

现在有越来越多的公司开始支持比特币支付,如新蛋,戴尔,微软等。Paypal 也已经宣布支持比特币支付。也有很多创业公司如 coinbase, bitpay 等为比特币提供类似支付宝的功能,使得商家和消费者更容易使用比特币。

机遇和挑战

比特币也面临着下面这些威胁。

安全性

因为比特币的核心是一串数字,只要得到这这串数字并能支配对应的比特币。这使得保存比特币变得特别不容易,丢失和被盗比特币的事情经常发生。比如最近的:bitstamp 被盗比特尔被盗比特币存钱罐被盗。目前常用的比特币保存技术为冷存储技术,即安装比特币钱包的电脑永不联网,离线生成地址和交易信息,再通过在线的钱包广播交易。

被利用于非法用途

曾经运行在暗网中的丝绸之路是世界上最大的在线毒品和枪支的交易网站,而比特币是其唯一支持的支付方式。虽然丝绸之路网站被美国 FBI 查封。但无数个类似的网站马上建立了起来。国内也出现大量利用比特币概念的传销组织,骗取了大量人的钱财。

政府的政策

在中国,央行是不承认比特币的货币属性的,而是定性为了商品。银行和第三方支付也不被允许参与比特币,这使得比特币交易所的正规化变得十分困难。在美国,目前参与比特币也面临着法律监管的难题,银行对比特币敬而远之。在全球,很多国家禁止了比特币交易,很多银行也视比特币为威胁。

交易所风险

曾经最大的比特币交易所 MT.GOX 的破产,无疑严重的打击了比特币参与者的信心。还有一些其他交易所的跑路,被盗等等,卷走了大量投资者的资金。长期投资者唯一应对的办法是尽快把比特币提现到自己控制的钱包中。

个人的看法

我2011年接触到比特币,2013年开始参与比特币交易,2014年加入了比特币相关的创业团队。不过由于各种原因,目前已经离开了这个创业团队。目前仍在参与比特币交易。

对于比特币,我是长期看好的。比特币目前仍然处于其发展的早期,比特币的价值体现在认同比特币的人数上。比特币的未来会是什么样的,在金融体系中起到什么作用还很难说。对于普通人,可以把比特币当做一种风险投资来看待。

读《Just for Fun》

最近读了 Just for Fun 这本书,这本书是是 Linux 之父 linus 的自传,中文名译作《只是为了好玩》。关于 Linux,我大学的时候做过一个介绍的 PPT

关于这本书起始很早就下过电子版,但看了一点就没看下去。读电子版书籍的体验差实体书太远,之前买了一个 Kindle 也很久没用过了。

Linux 的诞生

Linus 出生在北欧的芬兰。芬兰是全球数一数二的发达国家,教育水平极高,这给诞生 linus 这样的人物提供了基础。Linus 的外公是一名大学教授,在 1981 年就有了一台计算机。那时候的计算机可不像现在的计算机主要是哪来娱乐的,只有基本的编程功能。linus 通过这台计算机,进入了计算机的世界。linus 可以说是标准的宅男,据他妈妈的话:“我有一个很好养的小孩,只要把他和一台电脑关在一个黑乎乎的小屋里,再时不时扔一点面条进去就行了”。芬兰有着非常长的冬天,每天日照时间很短,编程陪伴他过完冬天。

Linus 读了大学之后,开始接触到了 UNIX 操作系统,他在他的电脑上安装了他能找到的唯一相对有用的 UNIX 系统版本:Minix. Minix 是大名鼎鼎的《现代操作系统》一书作者 Tanenbaum 教授为了操作系统教学而编写的教学辅助系统。Linus 在这个系统的基础上做了大量的个性化工作以符合自己的使用习惯,打造成属于他的专属系统。然而,由于 Minix 只是 Tanenbaum 教授的教学工具,所以刻意限制了某些功能,也不接受第三方的补丁。Linus 不满意这个系统的终端仿真程序,准备打算自己写一个这样的程序。出于上述目的,也是为了更好地了解电脑的工作原理,他决定直接在裸硬件上开始实现。谁知道,这个项目,最终演变成了一个操作系统。

为了完成这个终端仿真程序,他开始做大量本来是操作系统的工作。由于 UNIX 操作系统对他影响很大,所以他准备完全按照兼容UNIX的方式来实现这个项目。有意思的是,他还找来了 POSIX (可移植操作系统接口)标准文档,根据文档来实现自己的系统。经过将近半年的忙碌,他终于完成了 Linux 的最初版本。他其实本来想把它叫做Freax,但他上传文件的FTP服务器管理员觉得这个名字太难听,就改成了 Linux.

Linux 一开始便是便是以开放源代码的形式发布。Linux 发布的消息放在了 Minix 邮件组里面。他的原意是作为一个 Minix 系统的替代品,结果吸引了很多对操作系统感兴趣的人去测试和使用这个系统,帮助把其他程序移植到 Linux 下,帮助提交BUG和补丁。就这样,linux 早已不是 linus 一人开发的操作系统了,而是无数个程序员,通过互联网协作开发出来的庞然大物了。

开源的意义

Linux 可以说是开源界最具有影响力的项目了。从一个个人的项目,通过开源模式,演变成为了世界史上最大型的协作项目。开放源代码最初不过是软件开发者们的共同理念,他们认为电脑的源代码应该是开放和共享,并将GPL条款——就是那个“反版权”许可证,作为开源运动的强有力工具。开源模式如今已经成为了顶尖技术持续发展的一种十分有效的方法。

开源运动如此神奇,其中最令人费解的一点,就是为什么会有那么多聪明绝顶的程序员愿意在完全无报酬的情况下去屈尊工作。在生存已经或多或少得到保障的社会里,金钱已经不是最大的动机了。众所周知,人们被热情驱使的时候,就能把工作做到最好。要是他们能享受工作的乐趣,更是如此。对软件工程师如此,对剧作家、雕塑家和企业家来说也是如此。在开源环境中,程序员不再是与公司里雇来的几个同行一起工作,而是与世界上最优秀的程序员一起工作。他们必须使出浑身解数才能赢得同行的尊重,这是一种更为高效的激励模式。

开源的实用与道德之争

对于 Linux, 选择开源更多是出于实用的目的。应为 Linus 相信,通过开源模式,能够做的更好。在开源界还有另外一种声音,就是自由软件精神领袖,理查德·斯托曼,所宣称的:所有软件都应该是自由的。这实际上是一种道德绑架。在这一点上,我认同 Linus 的看法。

生活的意义

Linus 认为生活有三层动机,分别是:生存,社交和乐趣,这三层是有先后顺序的。这也是本书名的来源。

基于Mysql的流水日志记录系统

什么是流水日志?说白了,就是用户的操作日志,包括 who, when, what, how, why 等等。以一个论坛的发表流水日志为例,可能需要记录发表者的帐号ID,发表时间,发表IP,发表内容,发表类型,所在的主贴ID等等。有了这些数据,事后很容易进行分析和统计。

流水日志的重要性是不言而喻的。再我负责的工作中,有很多种类的流水日志需要记录,以供日后的查询和建模分析,并且这些流水日志要记录的内容也经常需要扩展。我们一般使用 Mysql 来记录这些数据。

记录流水日志看似是一件很简单地事情,直接写入数据库就可以了。但当数据量大起来之后,在几千条每秒的量级下,很多原来不是问题的问题,就变成了问题。

首先业务程序直接写数据库是行不通的,就需要搭建专门的流水日志记录服务,通过网络进行通信。这个服务也不能直接写数据库,要有专门的进程(或线程)负责处理请求,另外有进程(或线程)负责写入数据库。或者简单一点的话,先写入文件,然后再定时的写入数据库,但这样会有延迟。每次一条的进行数据库插入速度会很慢,可以通过批量插入或Load in file的方式,以提高写入的效率。

其次,一旦涉及到每天几亿条数据的量级,对于 Mysql 来说,全部放在一个表里也是行不通的,这就涉及到分表的操作。最简单的,按自然时间分表,比如每天的数据写一张表里。分得太细的不方便查询,分的太粗数据量太大,查询也慢。另外,在按时间切分数据表的基础上,有时还需要按照某个具体字段再次分表,以减少单个表的数据量,提高查询效率。比如按用户ID取模,每天再分100张表。

另外,如果需要对字段进行扩展,也是一个麻烦事,如果系统设计的不好,很可能会在升级的过程中丢失部分数据。

一开始,我们是每个系统自己实现流水日志的记录,当然也就没做的很好,出过各种问题。并且,每次做一个新系统,都要重复解决上面的问题,很繁琐。

为了简化这个过程,我设计并实现了Logdb, 它提供一个基于Mysql的通用可配置化的流水日志记录系统。对于业务来说,只需要配置一下,然后调用自动生成的API就好了。会根据配置自动进行分表,如果是 MyISAM 引擎,会同时创建Merge表。并且支持自动删除过期不再需要的数据。扩展也很简单,能够自动识别新增的字段并且修改数据库,并且API是向后兼容的。代码已经开源,再这里,有兴趣的同学可以看一下。

Logdb使用UDP协议通讯,每次调用API就相当于向指定地址发送一个UDP请求。默认情况下Logdb是没有回包的。API也不会等待回包,这样调用API的开销是很小的,几乎不会对业务进程造成任何的延迟。UDP协议是不可靠的,不过在局域网内,UDP发生丢包的概率还是极低的。并且UDP在实现上相对比较简单,后续可能会添加对TCP协议的支持。

Logdb在实现上分为了3层,分别称为 Interface, Reciver 和 Worker,整体架构可以用下面这个简图表示(Windows 自带画图画的,比较挫)。

Logdb架构

其中最核心的部分是 Reciver 进程。Reciver 在收到请求后,根据配置和协议格式对消息进行解析,并生成对应的SQL语句。在默认情况下,为了提高入库的效率,不是每条日志都进行入库,而是缓存一定的时间,进行批量入库。因为对于 Mysql 来说,使用含多个VALUE的INSERT语句同时插入几行,比单行的 Insert 要快很多倍。在默认情况下,LogDB对每个表维护一个缓存,如果缓存时间超过 500ms,或者缓存长度达到 1MB,则进行入库操作。这对于人来说,可以说是实时入库的,查询上不会造成延迟。

因为入库是一个阻塞的操作,所以将入库的工作交给另一个独立的进程Worker 来做。Reciver 通过一个基于共享内存和文件的队列将 SQL 语句推送给一个 Worker。这个队列也是很有趣的:当Worker 没有即时处理队列中的数据导致队列内存满时,会自动把新的数据写入文件。这就保证即使在短时间内请求量超过Worker 进程能处理的量时,数据仍然不会丢失,而在正常情况下,又能避免大量的文件IO操作。

Worker 在入库时,如果检测到因为数据库连接断开而失败的情况,则把失败的数据放入另一个队列。当数据库连接恢复时,自动的重新入库这些数据。这就保证,即使在数据库发生异常或重启时,也不需要人为的干涉,更不会丢失数据。

那 Interface 进程做什么呢?其实 Interface 进程所做的工作非常简单:它将接受到的请求转发给 Reciver并等待回包。如果超过1s 没有收到 Reciver 的回包,那么同样把这个请求放入一个队列,等到 Reciver 有回包时重试。这就保证,即使在重启 Reciver时,新的数据也不会丢失。

Logdb 的配置使用 ini 格式,还是很简单易懂的,自带的配置文件是自说明的,在这里

扩展新的字段时,需要再原有字段的最后面添加。这是因为,Logdb 所用的协议是非常简单的:首先是简单地包头,然后是数据部分,数据是按照配置的简单地顺序排列再一起的。如果新增的字段放在了中间,那么在解析请求时就可能得到脏数据或者解析失败。为了在升级后兼容老的API,再解析请求时添加了简单地规则:如果请求包剩余长度为0,那么使用空值。

一开始是准备设计的更通用一点,希望能够支持多种数据库,但后来发现不同的数据库支持的字段差别还是挺大的,比较难实现的通用。我们用 Mysql 比较多,就只支持这一种好了。

微博比特币价格机器人

前几天看到 twitter 上有一个机器人帐号 btcprice , 会定时报告各大交易所上比特币的最新成交价,觉得蛮有意思的,不用盯盘了,刷刷微博就能跟踪行情。心想微博上应该也应该有类似的帐号,搜了一下,竟然没有,所以就在微博上把 btcprice 注册了。今天有空折腾了几个小时,现在看起来似乎可用了,微博地址:http://weibo.com/btcprice  欢迎关注,目前只提供了 OkCoin 的数据。

做这样一个微博机器人其实很简单,类似的帐号有古城钟楼,这个帐号每个时辰报一次时间。据作者微博称,为了实现这个功能,写了三万多行代码。有点夸张了,不知道古城钟楼还有什么特殊能力?btcprice 这个帐号所有代码只有 48 行,实现一个微博机器人没有想象的那么难。

首先需要到 http://open.weibo.com/ 注册成为开发者,建议使用你注册的机器人帐号登录,这样会方便些。创建一个应用,类型选择网页应用。创建完成后,会获得 App Key 和 App Secret,其实对于机器人帐号来说,这两个字段没太大用处。应用审核通过需要提交开发者实名认证信息,但不审核也不影响调用微博发表接口。不过没有通过审核的应用,状态为测试中,授权的帐号只有1天的有效期。不过据称,对于开发者的帐号,授权有效期为5年。这就不需要担心授权过期的问题了。

发表微的API: http://open.weibo.com/wiki/2/statuses/update 对于一个机器人帐号来说,填两个参数就够了,一个是 status 就是要发表的微博消息,还有一个是 access_token。我一开始就卡在获取 access_token 上了。根据文档,access_token 必须通过 OAuth2.0 获取,而实现一个OAuth2.0 流程还挺麻烦的,况且机器人帐号只需要一次性授权拿到 access_token 就好了,最好有现成的东西可以获取。我想到一个办法是:在我的 wordpress 上安装一个社会化插件,填上在创建应时是获取的 App key 和 App Secret,然后用机器人微博帐号登录到自己的博客上,博客插件应该会通过某种方式把 access_token 保存起来,拿到 access_token 就万事大吉了。不过不知道什么问题,总是授权失败。Google 了一下可能是应用地址设置的问题,和回调地址不匹配。遂改了应用地址,但需要一段时间来生效。后来,看到微博开放平台上有一个API测试工具,http://open.weibo.com/tools/console 点进去就看到开发者自己的  access_token 了,真是踏破铁鞋无觅处得来全不费工夫。

获取比特币最新成交价格通过 OkCoin 的行情API获取 https://www.okcoin.com/t-1000052.html。接口返回的是一段 json 数据,使用 Python 中的 json 模块处理。Python 代码如下:

import urllib2
import json

def get_okcoin_btc_price():
        url = 'https://www.okcoin.com/api/ticker.do'
        r = urllib2.urlopen(url)
        data = json.loads(r.read())
        return float(data['ticker']['last'])

获取到价格后格式化消息体,然后调用微博的发表接口发布微博,Python 代码:

import urllib
import urllib2

        post_data = urllib.urlencode({'access_token' : access_token, 'status' : msg.encode('utf-8') })
        post_url = 'https://api.weibo.com/2/statuses/update.json'
        r = urllib2.urlopen(post_url, post_data);

完整代码可以在 github 上查看:https://github.com/haipome/btcprice/blob/master/btcprice_update.py

最后设置 crontab 每隔 30 分钟更新一次,程序部署在我的位于日本 linode 上。

TODO:

  1. 添加其他交易所数据
  2. 比特币价格监控,有大的波动时发表微博

读了点 redis 的源码

很早之前边对 redis 有所耳闻,但了解不多,直到前不久看到《V2EX 从过去一年半中学到的几件事》这篇文章。文中提到 redis 可以替换掉 Mysql 而单独使用,吃惊了不少,准备下决心研究一下 redis. 加上前不久看过部分 twemcache (twemcache 是 twitter 的 memcache 改写版,以下简称 memcache)的源码,所以这里结合这两者分享一下心得。

redis 是一种纯内存的、key-value 的数据库,NO-SQL 的一种。它的 value 支持 string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hashs(哈希类型)。redis  还支持持久化和主从复制。

相比之下,memcache 就纯粹多了。memcache 是一种纯内存的 key-value 缓存系统,value 类型只是一段 buffer,不支持持久化,不支持主从复制。

redis 和 memcache 都是使用 ANSI C 实现的,代码质量和可读性很高,非常有学习价值。

redis 中的数据结构

我读 redis 源码时主要读的是 redis 内部使用的一些基本数据结构。这些数据结构都是非常通用的。

sds:Simple Dynamic String,简单动态字符串。是 Redis 底层所使用的字符串表示, 它被用在几乎所有的 Redis 模块中。它很简单,就是一个带长度的、能自动扩展的、基于堆内存的字符串,并且兼容 C 中的字符串。

adlist: 双向链表,链表这东西已经被无数程序员实现过无数次了,无需多讲。

dict: 字典,有趣的是它扩容的过程。每个字典内部有两个 hash 表,一般用第一个,当发现 hash 表容量太大需要扩容时,创建第二个 hash 表。这时候不能一下子把第一个 hash 表里面的数据全部导入到第二个 hash 表,因为这样可能会导致阻塞。而是在每次执行查找或添加等操作时,从第一个 hash 表迁移一个节点到第二个 hash 表,这样像愚公移山一样直到扩容完毕。

skiplist: 跳跃表,这个数据结构也很有意思它,它是一种有序链表,加上随机化数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作需要O(log n)平均时间)。它的原理可以查看这篇文章 http://dsqiu.iteye.com/blog/1705530

ziplist: 一种压缩链表 ,使用压缩型的数据结构,减去指针的消耗,能够显著的减小对内存的使用。list, map, zset 在数据量小于特定值时,都是使用的 ziplist 以降低内存的消耗。

另外还有 intset, zipmap 等数据结构,不做多述。

 redis 的主从复制

redis 的 master, slaver 实现的可以说是相当优雅,浑然天成。关于主从复制与同步的问题,之前在工作中也遇到过,但苦于没找到一个更好的解决方案。主从结构的同步需要一次全量同步和后续的增量同步,同步的关键在于顺序,比如先 del 一个 key, 然后 add 这个 key, 如果同步成先 add 然后 del 的话,数据就不一致了。redis 的做法是,在收到同步请求之后,利用其持久化的能力,生成一个 RDB 内存 dump 文件,在生成 RDB 文件的同时,维护一个从这时候开始所有所有写操作的链表。RDB 文件生成好后,发送给 slaver, 然后再把生成 RDB 文件时所有的写操作命令发送给 slaver 执行 ,这样 slaver 就完成了一次全量更新。接下来 master 每次执行写操作时都会同步给 slaver。

redis 与 memcache

关于内存分配:memcache 的主要卖点便是其内存的分配。memcache 实现自己的内存分配是因为 glibc 自带的 malloc/free 性能太差,并且容易出现内存碎片。memcache 通过被称为 slab 的内存分配机制对内存进行管理。而 redis 没有自己分配内存,而是使用了第三方的内存分配器。redis 源码自带了 jemalloc, 也可以使用 google 的 tcmalloc, 这两者性能都很高,并且几乎 不会出现内存碎片问题。

关于事件处理:memcache 使用了开源的 libevent  进行事件的处理,包括网络IO和定时器。而 redis 则根据其不依赖的原则,实现了自己的事件处理库,对 epoll 等函数进行了封装。

关于配置:memcache 使用 getopt 进行命令行解析,只支持命令行参数形式配置,不支持配置文件。而 redis 同时支持配置文件和命令行。redis 解析命令行时,没有使用 getopt 等标准化命令行解析工具,而是自己通过 strcmp 进行解析,一开始觉得这个做法相当丑陋,后来发现自己误解了 redis 作者的苦衷了。redis 把除了 –help –version 等基本参数之外的其他 — 开头的参数,去除前面的 –,加入到一个字符串中。如果有配置文件,也把这个文件的内容一并读进这个字符串,然后由统一的函数对这个字符串进行配置解析。这样,就统一了配置文件和命令行参数,只要配置文件中有的,都可以通过命令行进行配置,个人觉得非常巧妙。

关于线程:memcache 是多线程的,由一个主线程处理连接,调度其他线程处理请求,充分利用多核 CPU 的能力。而 redis 是单进程的。严格说来,redis 是线程和进程混合的,它使用线程来进行 fsync ,也使用多进程利用 fork 的 copy-on-write 特性进实现 RDB 的持久化。但redis 在处理请求时,是单线程的。为什么不使用多线程,一个是因为对于处理内存数据,单线程已经够快了,另外,单线程能够提供一定的事务特征。为了充分利用资源可以在单台机器上起多个 redis 实例。

redis 的性能

redis 自带了基准测试工具 redis-benchmark 测试常用命令的性能,根据测试,一般的 GET SET 命令单 CLIENT 阻塞调用时,都可以达到上万次每秒,可以说大部分场合已经足够使用了。

参考:

redis 官方文档

Redis 设计与实现