0%

Requests 是 Python 最常用的 HTTP 包,API 封装的精美而且简单易用,不过没想到官网的第一个例子就有严重的潜在性能问题。

公司项目有需求去对用户的网页进行实时抓取,虽然 Python 很慢而且有 GIL,不过我一开始的判断是因为网页抓取是个 IO Bound 的操作,即使是单机,每秒并发度也应该至少 > 100。然而,性能测试发现能承受的每秒并发度 < 5…

大概源码是

1
2
r = requests.get($SOME_URL)
text = r.text # 慎用

原因是这样,为了用起来方便,如果想要的是 text (str) 那么 requests 会做一次对原始字节流的解码,如果网页给出了编码可以直接用,但是有相当一部分的网页没有指定编码,这时候 requests 会在内部调用 chardet 去猜最可能的编码,这个包相当慢,而且是 CPU Bound 的,Python 的 GIL 在这种时候就雪上加霜。

requests 的 issues 每隔一段时间就有人报告这个问题,比如 response.text is too slow, 我认为还是应该引起官方重视的,在性能重要的场景相当容易用错!

解决办法是不要直接用 text, 改用 content (binary),然后调用更快的 chardet 包

Python 用起来很爽,自带电池,不过应用在要求性能的生产环境还是需要更加详细的设计,评估和性能测试。

总是觉得自己已经很小心了,没想到前两天被发现了线上的大bug,因为判断相等失效导致逻辑混乱数据库里面记录了很多脏数据,大概意思是下面的逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class A
{
public string Name { get; set; }

public bool Equals(A a)
{
return Name == a.Name;
}
}

class Program
{
public static bool Test<T>(T a, T b)
{
return a.Equals(b);
}

static void Main(string[] args)
{
var a = new A {Name = "xyz"};
var b = new A {Name = "xyz"};

Console.WriteLine(Test(a, b));
}
}

希望输出的是true,可惜输出的是false。致命错误是没有去重载object上面定义好的默认Equals函数,这个例子里面UT没有测出来问题因为如果是直接作比较是没有问题的,但是在泛型函数里面绕了一下因为这个泛型类T并没有写约束,实际上调用的Equals是object的default Equals只是比较reference equals的。

以后切记这些基础Equals, GetHashCode, ToString 要用override保证做了正确的重载

从8月1号开始合约建仓到今天下午平仓,1800 USDT 滚成了 6055 USDT,年化收益率1000% 左右,难能可贵的是上百次交易没有一单是亏损的。当然也几乎次次都没有踩到完美节奏,有必要总结一下经验与教训。

什么是加密货币

参考维基,我并不懂,大概理解是用加密算法保证了稀有程度的货币,代表是最早的比特币,后来根据类似的原理设计出了很多种不同类型的加密货币,比较著名的有

等等。

怎么交易加密货币

交易加密货币类似于炒外汇,因为有很多不同类型的加密货币,交易就是不同币种之间的兑换,但是怎么跟法币兑换呢?最常见的办法是有一类加密货币叫稳定币,价格锚定美元或者别的法币,比如常见的 USDT, USDC 等等,实际操作时我习惯先用法币购买 USDT, 然后用 USDT 交易,因为 USDT 本身也是加密货币是可以方便的在各个交易所-个人钱包之间转账的。几家大的交易所包括

什么是永续合约

这里有详细的讲解。需要记住的是这是一种永不到期的期货,使用资金费率来保证合约价格锚定现货价格,可以方便的加杠杆来做多或者做空。

为什么选择交易加密货币永续合约

我这里跟美股做一下对比

  • 加密货币价格波动很快,一天的上下波动可以对比一个月的股票价格波动,相当于资金利用率大大提高
  • 因为是期货所以做空很方便,不会出现借不到现货的情况
  • 杠杠不需要付昂贵的利息,在多空双方实力一致的理想情况下,资金费率的期望应该是0,也就是没有额外的借款成本,交易量比较大的币种实际上就是趋近于0的
  • 市场还是不够成熟,追涨杀跌非常常见,对手盘交易模式有规律可循

我的交易策略

因为我极度厌恶风险,所以操作上是优化本金不失而不是追求更高利润。上面说过价格波动模式很有规律,在最近的时段上看类似于一个正弦曲线,当然价格围绕价值变动也是很合理的,同时,我们能看到这个波动偶尔会陡然升高,然后再次回归价值,抓住大的波动就是这个策略的关键,我把他叫做钓鱼,三步走

  1. 选择一个小规模的币种监控列表,这里我会剔除所有的新币,因为不知道他们会稳定在什么价格附近
  2. 监控价格大规模起伏,不同币种不同时间阈值不一样,例如 10% - 20%,反方向下单
  3. 最关键的是这一步,方向反转之后,有盈利就撤,我是只赚 2%

实际操作中会碰到很多细节的问题,例如杠杠倍数选择,推荐从4倍开始练手,不推荐超过5倍。如果趋势没有当场发生发转,需要持续补仓,推荐任何时刻不要超过半仓以防不测

为什么不用套利策略?

有人会说如果厌恶风险那为什么不采用套利策略呢?最开始研究过期现套利,写了模拟程序跑了一下,两个问题

  • 抓到的基差很小导致去除4次手续费后几乎无利可图,可能是因为套利的机器人太多了稀释了利润
  • 期现套利需要短时间两边下单,但是没法保证两单一定能成功,这就需要复杂的机制来进行事故处理,例如主动滑点吃单等,进一步压缩利润里

另外我有个朋友的期现套利实盘因为种种原因暂停了更坚定了我的想法

单边行情怎么办

事实上第三步就是为了防止市场单边行情,有盈利就空仓,实际上从没碰到过每个小时线都是持续上涨没有任何回调的行情。合理的仓位管理是能保证平摊成本在最坏情况下一定离定点不远,等待回调,不要用太高的杠杆也是为了出现最差情况后不会被强行平仓。

数独是流传很广的经典问题,本身就挺有意思。计算机求解搜索加回溯也是经典的入门问题,我就经常拿来当面试问。

计算机求解数独有很多脑洞大开的办法,比如数独可以看作一个特殊的二元可满足性优化问题,所有的最优化方法都能直接应用,直接调solver或者一些非梯度优化算法(蚁群算法,遗传算法,模拟退火等等)

我觉得最有意思的是前几年的一个github repo,Can Convolutional Neural Networks Crack Sudoku Puzzles?,暴力的把数独填充当作矩阵补全问题,通过卷积神经网络训练几百万对数独问题和答案,做到了86%的准确率。相信加更多的层数和更新的架构可以进一步的提高准确率。最有意思的是能看出来数独竟然是可以训练的,有一点反直觉。

但是做不到100%准确率是个遗憾,我就把这个方法向前再推一步,依然使用卷积神经网络进行训练,但是对于每一个未知的格子不再单纯的填概率最高的数字,而是拿到每一个格子对应的数字概率分布,使用这个信息来加速搜索。具体的做法是搜索到某一个格子,优先尝试概率最大的数字,同样会执行失败回溯。做了简单的perf测试,对于平均情况,搜索次数略有减少,但是因为多了一次大开销的inference,实际耗时半斤八两。有一个比较大的优势是新的搜索方法更稳定,可以保证每一个问题都能很快求解,对于极端例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
>>> hard1  = '.....6....59.....82....8....45........3........6..3.54...325..6..................'
>>> solve_all([hard1])
. . . |. . 6 |. . .
. 5 9 |. . . |. . 8
2 . . |. . 8 |. . .
------+------+------
. 4 5 |. . . |. . .
. . 3 |. . . |. . .
. . 6 |. . 3 |. 5 4
------+------+------
. . . |3 2 5 |. . 6
. . . |. . . |. . .
. . . |. . . |. . .

4 3 8 |7 9 6 |2 1 5
6 5 9 |1 3 2 |4 7 8
2 7 1 |4 5 8 |6 9 3
------+------+------
8 4 5 |2 1 9 |3 6 7
7 1 3 |5 6 4 |8 2 9
9 2 6 |8 7 3 |1 5 4
------+------+------
1 9 4 |3 2 5 |7 8 6
3 6 2 |9 8 7 |5 4 1
5 8 7 |6 4 1 |9 3 2

(188.79 seconds)

甚至能加速三万倍。详细代码和样例放在了github上面:sudoku-neural

可以进一步思考的地方比如经典数独问题是9x9的样本空间,暴力搜索+启发式规则+剪枝还是可以算的动的,如果推广出去比如15维或者19维这样子呢。大胆的猜想是在某个临界值会出现只有使用神经网络训练加速搜索才能在有限时间求解,有时间我会跟进一下。

这里面的优化是非常朴素的,把(领域知识 + 启发式规则)变成一个模型来求解了一个特定的最优化问题。那么这个思路能不能推广到最优化solver上面呢,像是cplex或者gurobi这种之所以这么快最大的秘密我猜是启发式规则写的好,能不能使用某种数据来训练一个通用的模型来加速搜索?具体的优化问题和深度网络结合也是这几年的热点之一,Bengio有一篇综述:Machine Learning for Combinatorial Optimization: a Methodological Tour d’Horizon可以参考一下,目前的工作都不太实用,处于探索性阶段,最大的问题还是如何建模,数独问题偏偏就有这么简单清晰的模型(不用处理自己就是2维或者3维的tensor)能不能打开新的思路呢?

前几天在项目中碰到个问题,同事告诉我西雅图方圆50英里有1000多个城市,直觉这个数据量级有问题,怎么快速验证一下呢?开地图是一个办法,不过有点儿麻烦,假如这是500英里那真的数不过来了。简单点50英里开不到华州的边界的,如果我知道华州总共的城市也不到1000的话就反证了这个结论是错误的。

Google一下 “how many cities in washington state”,第一条是wikipedia,给了几个列表,可是没工夫对这种小事儿浪费时间呀。

想起了之前听说Wolfram吹自己的产品QA的功能做的非常好,万一就管用呢,试了下,效果还真挺满意的。链接

wolframalpha

可惜免费版的功能有限制,计算时间也有限制,我找到了这个网站可以免费使用pro版

试验一下推给我的这个知乎问题: 求助,100!+101 是不是质数?,1秒给出答案

wolframalphapro