Blog

  • CMake剖析

    工作机制

    module

    封装一系列可复用的功能,方便使用,分为内置Module与自定义Module

    Cache

    target

    构建的产物,比如executablelibrary

    常用Module、命令

    include

    从一个文件或者Module加载CMake代码

    CMakeDependentOption

    cmake_dependent_option

    定义条件选项,在一定条件成立时才生效

  • 【BTC源码系列】随机漫步Day1

    程序入口

    比特币源码是用C++写的,构建系统用的CMake,在CMakeLists.txt中可以找到add_executable命令,含义是最终构建的二进制产物,此命令的参数中会指定源文件。

    重要设计

    主流程

    • 创建全局上下文
    • 连接服务端信号处理函数
    • 解析命令行参数
    • 启动程序

    数据结构

    疑问

    • noui_connect貌似是注册UI事件的,但是名字又叫noui

    欠缺的知识

    • C++命名空间的规则
      • 实际的大型项目中常用的idiom,即编程惯用法

    参考资料

    • 比特币node启动的命令行参数
  • 【BTC源码系列】开篇词

    进入加密货币行业4个月了,懵懵懂懂做了一些公司业务的需求,学了一些加密货币行业的皮毛知识,每天挂在嘴边的尽是些上链、签名、EVM、手续费等似是而非的名词。另一方面,Web3给我的体感是还在不断涌现新的项目,每次点开项目官网都有一种眩晕感,一开始还觉得这个项目又引领了一个创新,解决了Web3的重大难题,但是慢慢地,新鲜感一过,感受到的只有麻木,而且那么多币经我的手上链,感觉自己的提升并没有多少,只是对公司内部的技术栈以及工作流程更熟悉了而已。

    静下心来想了一段时间,加密货币毕竟在国内游走在灰色地带,生态没有起来,中文社区的技术沉淀不够,对于新人入门很不友好。英文资料浩如烟海,虽然英语阅读对于我来说不是不可逾越的门槛,但是却也实打实地影响我的学习效率,一开始也想沉下心来慢慢学,但是时间被业务裹挟,始终没有开始做。终于,这段时间感觉学有余力了,狠狠心踏上BTC源码的学习之路。

    值得投入时间吗

    直接说答案吧,值得!从大的方面讲,有以下两点:

    • 加密货币行业依然处在扩张期。以2024年末尾比特币价格首次突破10万美元为标志,比特币不可避免会在人们心中种下一颗种子,一颗将成长为比肩甚至超越黄金的种子,比特币还远远没有结束。现在投入时间肯定是最优选择。
    • 希望我能获得一张进入开源世界的钥匙。这个角度是从我的个人发展角度论述的,三年,我的三年程序员生涯只是让我获得一些打工的技能,而且这个技能还不算特别突出。学生时代见证了诸多互联网大佬的崛起,从财务自由走向财务自由,却并没有激发我的欲望,可能是前面20年走的太顺了吧,一副无所欲无所求的样子,这个其实不对的。我的状态应该切换过来,趁着现在还有接受新事物的能力,去疯狂尝试,疯狂试错,找到自己真正感兴趣与擅长的。如果可以做到,我希望是从这个事情开始。

    要做成什么样

    一次做到完美不可能,粗略想了一下,分以下几步走:

    • 对整个项目有框架性的了解,包括项目设计、技术栈,尤其是结合比特币概念展开,具体的实现细节不需要很清楚,做到有问题能知道去哪里找就行了
    • 回馈开源社区。到github上找几个没有解决的issue,尝试解决,走一遍完整的issue修复的交付流程
    • 深入代码的实现细节,了解现有实现的局限,能跟得上社区大佬的前沿讨论,做一个专家
    • 钻研区块链的分布式算法,主要是代码

    路径与方法

    • 早睡早起
    • 前期速度可以慢,静下心来把C++、CMake搞清楚
    • 公司报销了Cursor的订阅费,后期尝试利用AI加快阅读源码速度
  • C++宏特性

    背景

    宏(Macro)是C++里的一个让人又爱又恨的特性,非常难以掌握。然而,悲剧的是,许多大型C++项目中宏的使用满天飞,因此宏是一个C++程序员难以摆脱的特性,我们有必要梳理一下宏的用法。

    特性

    #(井号/Hash Symbol)

    • 单独一个#放在宏定义参数的前面时,语义为将宏定义的参数转换为字符串常量
    • 连续两个#放在两个宏定义参数的中间时,语义是将两个宏定义参数拼接为一个符号。
  • 共同基金和其他投资公司

    投资公司

    投资者通过投资公司进行投资有以下几个方面的优势:

    • Record keeping and administration
    • 多样性和分散化
    • 专业管理
    • 低交易成本

    资产池化(Pooling of Assets)是投资公司运作的关键,投资者通过购买投资公司发行的份额来获得对于投资公司所管理的资产的所有权,所有权的大小与持有的基金份额成比例。

    资产净值(net asset value/NAV)

    (1)   \begin{equation*} \text{Net asset value} = \frac{\text{Market value of assets minus liabilities}}{\text{Shares outstanding}}\end{equation*}

    投资公司的类型

    Unit Investment Trusts

    Managed Investment Companies

    Managed Investment Companies分为两类:开放式基金和封闭式基金,二者主要有以下异同:

    • 认购/赎回的对手方:开放式基金为基金本身,封闭式基金为其他投资者
    • 认购/赎回价格:开放式基金为资产净值,即NAV,封闭式基金可能偏离NAV
    • 销售费用:开放式基金在认购/赎回时可能会收取销售费用,使得价格略高于NAV,英语里称这种情况为carry a load

    其他投资公司

    • Commingled Funds
    • REITs
    • Hedge Funds
  • 【踩坑记录】Failed to enable crypto stream_socket_client

    自建的Wordpress的health check总是失败,显示以下错误:

    /wp-json/wp/v2/types/post?context=edit
    The REST API request failed due to an error.
    Error: stream_socket_client(): SSL operation field with code 1. OpenSSL Error messages: error:0A000410:SSL routines::sslv3 alert handshake failure stream_socket_client: Failed to enable crypto stream_socket_client

    解决办法:

    • 安装php curl模块,例如apt install php7.4-curl
    • 重启apache2 systemctl restart apache2.service

    本人走了一点弯路,通过apt安装wordpress的时候,php作为wordpress的依赖被自动安装,不过版本是8.3,然后就卸载了php8.3,安装了php7.4,发现site check还是不通过,最后安装了php7.4-curl才解决,没有试过在php8.3版本安装php8.3-curl是否可以解决问题。

  • 风险、回报与历史记录

    利率水平的决定因素

    • 储户的储蓄供给,主要是居民
    • 商业的资金需求
    • 政府部门经中央银行调整后的资金需求

    名义利率与实际利率

    (1)   \begin{equation*}     rr \approx rn - i\end{equation*}

    (2)   \begin{equation*}    1 + rr = \frac{1 + rn}{1 + i}\end{equation*}

    (3)   \begin{equation*}     rr = \frac{rn - i}{1 + i}\end{equation*}

    其中,rr代表实际利率,rn代表名义利率,i代表通货膨胀率。根据(3),近似公式(1)高估了实际利率。

    税与实际利率

    不同持有期的回报率比较

    本小节以债券为例进行讲解,而且是一种特殊的债券,叫零息债券,投资者可以用低于面值的折扣价认购,最终的收益完全取决于认购价和面值的差额。另外多说一句,在英语资料中,常常会出现”par value”这个词,比较专业,一般翻译成对价,没有做深入的研究,可以理解成一个东西标明的价格。

    首先约定几个数学记号,T表示持有期限,以年为单位,P(T)表示期限为T年的有价证券的申购价,r_f(T)表示期限为T年的有价证券的总回报率。

    有效年化率(Effective Annual Rate, EAR),它有这样一个特性:在按复利方法计算后可以得到相等的总回报率。

    风险与风险溢价

    持有期回报率(Holding-Period Returns),是任意时长的持有期内,某项资产的回报率

    (4)   \begin{equation*} HPR = \frac{\text{Ending price of  a share} - \text{Beginning price} + \text{Cash dividend}}{\text{Beginning price}}\end{equation*}

    公式(4)考虑了分红,但分红发放的时间早于截止时间点,这一点是被忽略了的。分红产生的回报百分比称作分红率(\textbf{dividend yield}),因此分红率加资本利得就等于HPR。

    未来一段时间的\textit{HPR}通常带有很大的不确定性,为了量化这种不确定性,引入了概率论里的期望与方差(或者标准差)。

    随机变量s表示未来金融市场的表现,p(s)表示该表现出现的概率,r(s)表示在该表现下的\textit{HPR},那么期望回报率可以表示如下:

    (5)   \begin{equation*} E(r) = \sum_{s} {p(s)r(s)}\end{equation*}

    投资工具的风险一般用标准差来衡量,公式如下:

    (6)   \begin{equation*}\sigma^2=\sum_{s} {p(s){[r(s)-E(r)]}}^2\end{equation*}

  • Python类型系统

    分类

    Structural typesNominal types
    Runtime checkingDuck typingGoose typing
    Static checkingStatic duck typingStatic typing
    表1 Python类型系统分类——动态/静态类型检查、显式/隐式声明类间的继承/实现关系

    两种结构化类型的形式

    本小节讨论表1第一列中的两种类型系统。

    首先解释清楚一个概念,协议或者protocol,在Python中,这个概念可以理解为一个方法集合,其中的每个方法都有约定好的签名和语义,但在不同的类型系统下,对于用户自定义类的实现要求是不一样的。

    对于Python原生支持的duck typing,程序员可以不必实现协议中的每一个方法,但是只在PEP 544被采纳之后才支持的static duck typing,严格要求实现协议中的每一个方法。在Python社区中,前者称之为动态协议,后者称之为静态协议,如果未明确指明的话,一般指动态协议。

    两种形式的共同点是都无需显式声明所实现的协议,会有相对应的方法检查类的方法集合。

    Duck typing编程

    防御式&Fail Fast

    防御式编程的目的是增强程序的安全性,而Fail fast一方面通过尽早抛出异常来避免不可预料的后果,另一方面也便于定位问题,提高升序的可维护性。

    那么我们如何发现异常呢?是不是需要程序员一条条编写检查代码呢?答案是否定的,而且用一句话就能解释,EAFP,懂的都懂,不懂的看下面。

    EAFP

    It’s easier to ask for forgiveness than permission

    EAFP带给Python一种很不一样的特质:把思考聚焦在程序的正常执行流上,进而保持思维流的连贯。当然这也得益于Python语言精心设计的Exception类层级。

    Goose Typing

    Python中没有直接定义Interface这个概念,但是ABC(Abstract Base Class)充当了这一功能,使得程序员可以对现实世界的东西建模,定义语法和语义都严谨的一组方法,然后配合Python自带的isinstanceisubclass函数,可以在运行时灵活地对对象进行自省。

    Goose Typing算是对Duck Typing的一种补充,允许适当且适量地使用isinstance,并且第二个参数必须是ABC而不是具体类型。

    多继承

    菱形继承

    在一个菱形的继承关系中,有可能出现命名冲突的问题——互为兄弟节点的两个类各自有自己的方法实现。当出现这种情况时,每种语言都要有一套决议(Resolution)方案,Python的方案为mro,即Method Resolution Order。

    mro存储在类的一个名为__mro__的属性中,是一个元组。

    super函数

    super这个名字可能有些误导,会让人以为会返回当前类的父类。首先先摒弃掉这种望文生义的想法。其次,super的工作机制与mro紧密联系,具体来说,mro决定了在一个多继承关系中类的方法激活顺序,而是否被激活取决于方法的实现是否调用了super。如果调用了super,那么调用链将沿着mro继续;如果没有,调用链就结束。因此,super函数是协作式的。

  • 保证金交易

    定义

    保证金交易,也叫垫付交易,英文叫Buying on Margin,是指投资人基于自己对证券价格未来走向的预测,从券商获得”贷款”来放大投资收益的行为。”贷款”之所以加引号,是因为此处它的含义不仅局限于现金,还包括其他可以换成钱的有价证券。

    术语

    保证金(margin)

    broker’s call loans

    保证金率(Percentage Margin)

    保证金率,也叫保证金比例,是指投资者的自有资金占总投资额的百分比。从资产负债表的角度看,就是所有者权益占总资产市值的百分比。

    初始保证金(Initial Margin)

    维持保证金(Maintenance Margin)

    追缴保证金(Margin Call)

    举个例子

    AssetsLiabilities and Owner’s Equity
    Value of stock $10,000Loan from broker $4,000
    Equity $6,000
    表1 投资者在保证金交易后的资产负债表

    规则

    • 进行保证金交易的成本有2个方面:利息以及券商的服务费,不同券商之间会有略微差别,不会很大。
    • 发起保证金交易的时候,必须满足初始保证金要求。
    • 通过保证金交易获得的证券必须挂在券商的账户下,作为贷款的抵押物。
    • 投资者持有的头寸未清算(未平仓)时,券商会监控投资者账户的保证金率水平,保证其不低于维持保证金
    • 一旦投资者的保证金率低于维持保证金,券商会发起追缴保证金要求,投资者需缴纳足够保证金来使保证金率高于维持保证金;否则,券商会清算一部分头寸(平掉一些仓位)来恢复保证金率。

  • 比特币概念及术语

    • 挖矿难度
      • difficulty:相对值
      • target:绝对值,区块的哈希值必须小于等于它
      • bits:target的紧凑表示