之前使用整理 Evernote 代替品 的时候就提出了我自己的一个需求,就是有一个完善的 Web Clip 系统,Evernote 和 WizNote 都做的比较不错。但 Obsidian 并没有提供类似的工具,不过幸好 Obsidian 使用 Markdown 来管理文档,这样的开放程度使得我可以寻找一个将网页变为 Markdown 的浏览器扩展就能做到。
经过一段时间的调研和搜索我发现了如下这些可选项:
这三个插件都是开源的,各自有各自的特点,markdown-clipper 是我最早使用的插件,点击一下就可以将整个网页保存成 markdown 文件并下载到本地,而 markdownload 则可以在点击之后先预览一下生成的 markdown 调整之后再下载本地。obsidian-clipper 则可以选中内容,然后点击之后自动打开 Obsidian,然后新建并保存内容,但该插件处于早期开发阶段可能会遇上一些问题。不过我个人在 Linux 下尝试还是非常不错的,并且开发者还挺活跃。
不过一定要当心的是,别被可以无线膨胀的信息冲昏头脑,将网页内容存入 Obisidian 是为了后期阅读或消化,别放入之后便不再阅读。
所以我的方式是在 Obsidian 中单独新建了一个文件夹 Web Clip
所有摘录的文件第一站便是这个地方。一旦我有时间,就会向使用那个稍后阅读应用 Pocket/Instapaper 一样,将 Web Clip 文件夹中的内容按照次序阅读并拆解,并将重要的内容吸收到 Obsidian 之前的笔记体系中。一段时间之后 Web Clip 会自动清空。
我经过一段时间的使用之后,觉得 Obsidian Clipper 的使用最直接,选中,点击,然后就自动打开 Obsidian 新建了笔记。但目前为止唯一让我不太满意的就是有的时候无法调用起 Obsidian。这个时候就使用 markdownload 作为辅助。
配置:
{zettel}-{title}
#obsidian-clipper #web-clipper #markdown-clipper
{clip}
Clipped from [{title}]({url}) at {datetime}.
在使用一段时间之后,最终选定了 MarkDownload ,因为转换的 Markdown 文件格式最好,并且可以批量下载文章中的图片。
我在使用了半年 macOS 之后,又回到了 Linux 的怀抱,虽然 macOS 有其自身的优势,我也不否认 macOS 系统上软件生态的友好,但我发现即使我将日常开发主力机器装回到 Linux,也没有丧失操作系统的便捷性和易用性。这或许和我下意识的只使用跨平台的软件有关,并且最长使用的软件几乎都是一套快捷键。
一开始从一个系统切换到另一个系统的时候,难免会有一些东西需要学习,但是其内在的逻辑是一致的,操作系统无非是提高了上层应用运行时的环境。并且如今跨平台的软件越来越多,只要数据在我这里,无论在哪一个系统中都可以迅速地开始自己的工作。
这一次无意间迫使我回到 Linux 的原因之一就是我发现 macOS 并没有我想象的稳定,在最近的使用过程中经常发现一些古怪的问题,并且我无法自己解决,必须售后客服解决,这更让我意识到我不能完全依赖这一个系统,即使我每天备份,数据没有问题,但一旦发生致命性的问题,我依然需要借助客服去解决(当然这里要提一句苹果的售后客服确实是不错的)。
最近自动更新之后又发现了一个问题,/usr/libexec/secd
占用非常高的 CPU,然后导致风扇狂转。
幸而这个问题,我简单的搜索了一下之后就找到了解决方法,删除 ~/Library/Keychains
目录并重启电脑。这个目录中保存了本地的 Keychain 一些密码,网上的说法大概率和 Keychain 的更新机制有关系。
我一度以为 macOS 上的应用质量很高,但实际使用后发现,确实在日常使用上高于 Linux 上大多数的应用,但是 macOS 上依然会发生 Application Not Responding 的问题,即使我的配置是 i9+32G,也时不时的出现转圈。
记录一下常用的命令:
Bitwarden
sudo snap install bitwarden
Chrome
sudo apt update
sudo apt install google-chrome-stable
zsh, tmux, vim, rime,
同步的配置
之前在 Twitter 上看到一套将 Linux 上的快捷键和 macOS 映射成一致的解决方案:
但是,在经过我的尝试之后我还是没有使用上面的方案,在终端中 macOS 上也是使用 Ctrl
,在 Linux 和 macOS 上使用大部分快捷键,我能用 vim-key-binding 就使用 Vim-key-binding 的,比如在 Chrome 中使用 Vimium,在 Obsidian 开启 Vim 快捷键映射,在 IDEA 中使用 Vim 插件,已经满足我大部分的日常使用。
今天用得好好的电脑突然三次黑屏,两次发生在早上刚刚使用的时候,一次发生在晚上回家之后。所以一怒之下就直接上官网联系了 Apple Support,但是也不知道是不是我直接登录的 .com
网站,在我提交了 Support 之后一分钟一个外国小哥打了电话过来,我一下子没反应过来,只能用着不那么熟练的英语开始了 macOS 修复之路。
我简单地向这位技术小哥描述了我的问题,大致意思就是系统突然崩溃了三次,然后在聊的过程之中,经过他的提醒,我发现出现问题的时候都是系统从睡眠状态中恢复,并刚开机不久,在打字的过程中,突然风扇很响一声,电脑就黑屏了。
虽然这个时候能启动,并且启动之后运行有没有问题,但是技术小哥还是提议清理一下系统的缓存,和 NVRAM,虽然在讲电话的过程中我并不知道 NVRAM 是什么,但后来查了发现 macOS 会在这一块区域存放一些硬件配置信息。
在技术指导的过程中,发现我的硬盘剩余空间只剩下了 27G,技术就判断这可能是因为磁盘空间不足导致,睡眠的时候一些系统的内存的缓存问题而导致的系统故障,然后又指导我清理了一下系统 Cache。
我就在技术的指导下,进行了一系列的操作,总结如下。如果有人遇到了相同的问题,可以自行先试试了。
我在网上查询技术小哥让我执行的操作时,发现其实做的第一步就是重置了 S.M.C。
技术先让我正常关机,等 Mac 完全关机之后,让我按下左边的 Shift,Control 和 Option 按键,然后同时按下电源键(Touch ID 开机键)并持续 10 秒时间。这个是重置 MacBooks S.M.C 的方法。这个步骤之后,重新按下电源键,笔记本会正常启动。
S.M.C 是 System Management Controller 的缩写,这是电脑上的一块微控制器,在 Intel 芯片的 Mac 上同来处理不同的电源,灯光,传感器等等硬件。
如果 Mac 不响应电源按键也可以尝试使用上面的步骤进行重置。
当你发现电池无法正常充电, Mac 无法识别插入 USB-C 端口的设备,或者键盘背光无法正常工作,或者睡眠功能运行不正常的时候,重置 S.M.C 可能是有用的。其他的症状比如系统的风扇高速运转,或者即使没有运行很多应用程序但 Mac 也运行迟钝,这时候重置 S.M.C 可能有效。
An S.M.C. reset may help if you notice things like the battery is not charging properly, the Mac does not recognize devices plugged into its USB-C port, the keyboard backlight is not working correctly or the sleep function is out of whack. Other symptoms include the computer fan’s running at high speed or the Mac’s acting sluggish, even if you are not using a lot of processor-hogging programs.
Apple’s support site has a full guide to the S.M.C. reset process for all its Intel-based Macs, including those with removable batteries and desktop models. The guide also lists a series of things you should try before resetting the S.M.C. While performing a reset does not generate an alert box or notification, you can tell if you were successful if the odd Mac behavior stops. (You may also have to redo any preferences for your display and power-management settings.)
重置 S.M.C 可能修复一些不确定的错误行为,但不会对任何电源的损坏或者硬件的故障有任何帮助。
现在的 Mac 会在 nonvolatile random access memory(NVRAM) 的地方存储一些设置。如果 Mac 无法操作音量,屏幕分辨率,时区信息,或启动影片,那么极有可能是存放在 NVRAM 中的信息损坏了。
你通过如下的方式可以 重置 NVRAM 或 PRAM :
在执行这一步之前请一点先做好系统的全盘备份,使用 Time Machine 将系统备份到外置存储中。
然后打开 Finder:
在打开的文件夹中删除 Caches
文件夹:
我在执行完这一步之后释放了大约100G的空间。
用了半年多 macOS,虽然不错,但工作用还是觉得 Linux 比较顺手,所以经过了半年时间还是从 macOS 切换回了 Linux。然而需要解决的一个问题便是我之前的 macOS 上使用 VMware Fusion 的个人授权安装了一个 Windows 用来进行一些调试,现在有一些配置因为需要依赖外部人员进行操作,证书之类的,只能想办法把 Fusion 上的虚拟机转移到 Linux 下的 VMware Workstation 中。
在正式迁移之前先了解一下磁盘上的几类文件,这些文件都是和 VMware 虚拟机相关的。
VMware 虚拟化软件比如 VMware Workstation 和 VMware Fusion 的配置文件。
存储使用「新建虚拟机向导」创建的虚拟机设置;包括内存、硬盘和处理器限制等。
VMX 文件使用纯文本格式保存,并包含配置 属性=值
。
比如,内存限制是
memsize = "2048"
表示虚拟机允许的最大内存为 2G。
Fusion 保存的 VMX 文件通常存储在 .vmwarevm
包内。
VMDK 文件表示 Virtual Machine Disk
,是 VMware 虚拟机的虚拟硬盘格式。通常 vmdk
文件包含这虚拟机所需要的所有文件。
经过一些调研,虽然 VMware的官网 写着可以通过菜单里面的 Export 来将虚拟机导出成 OVF 格式,但是我一查发现我用的并不是 Fusion Pro 版本,也没有这一个选项。
所以只能另找办法,后来发现有人发现了 VMware 这个命令行工具可以进行转换。
cd /Applications/VMware\ Fusion.app/Contents/Library/VMware\ OVF\ Tool/
./ovftool <PATH TO SOURCE VM's .vmx file> <PATH TO OUTPUT ova file>
# example
./ovftool --acceptAllEulas ~/Documents/Virtual\ Machines.localized/CentOS\ 6.5.vmwarevm/CentOS\ 6.5.vmx /tmp/CentOS6.5.ova
但还没进行尝试,就发现原来 VMware Workstation 和 Fusion 只是两个操作系统上的不同实现,其实虚拟机部分还是相同的,查看其硬盘上的文件,发现结构类似,文件类型也差不多,所以就萌生了先 scp
导过来看一下能不能直接使用的想法,经过一段时间的拷贝,发现 Linux 下的 Workstation 可以直接识别。
在迁移了 Windows 第一次启动的时候,报了一个错:
was created by a VMware product that is incompatible with this version of VMware Workstation and cannot be used. Cannot open the configuration file.
这个错一看就知道可能是版本不兼容的问题,我的 Fusion 是最新的 12 版本,而 Workstation 则是很多年前安装的 15 版本。后来查到可以通过修改 vmx
配置文件解决。
修改 vmx
中的 virtualHW.version
版本到一个比较低的版本即可。
二者对应的版本可以通过如下这张表进行查看。
Virtual Hardware Version | Products |
19 | ESXi 7.0 U2(7.0.2) |
18 | ESXi 7.0 U1 (7.0.1) Fusion 12.x Workstation Pro 16.x Workstation Player 16.x |
17 | ESXi 7.0 (7.0.0) |
16 | Fusion 11.x Workstation Pro 15.x Workstation Player 15.x |
15 | ESXi 6.7 U2 |
14 | ESXi 6.7 Fusion 10.x Workstation Pro 14.x Workstation Player 14.x |
13 | ESXi 6.5 |
12 | Fusion 8.x Workstation Pro 12.x Workstation Player 12.x |
11 | ESXi 6.0 Fusion 7.x Workstation 11.x Player 7.x |
10 | ESXi 5.5 Fusion 6.x Workstation 10.x Player 6.x |
9 | ESXi 5.1 Fusion 5.x Workstation 9.x Player 5.x |
8 | ESXi 5.0 Fusion 4.x Workstation 8.x Player 4.x |
7 | ESXi/ESX 4.x Fusion 3.x Fusion 2.x Workstation 7.x Workstation 6.5.x Player 3.x Server 2.x |
6 | Workstation 6.0.x |
4 | ESX 3.x ACE 2.x Fusion 1.x Player 2.x |
3 and 4 | ACE 1.x Lab Manager 2.x Player 1.x Server 1.x Workstation 5.x Workstation 4.x |
3 | ESX 2.x GSX Server 3.x |
在菜单栏 View 选择 Fit Guest Now.
Copy the VMDK file from the VMware Workstation virtual machine to the Mac running VMware Fusion.
Open VMware Fusion and create a new virtual machine.
Click “Continue without disk.”
Click “Use an existing virtual disk,” then double-click the VMDK file and click “Continue.”
Choose the operating system type, if prompted, then click “Continue.”
Select whether or not to run the virtual machine automatically.
Click “Customize Settings” to adjust the virtual machine’s allocated resources, such as CPUs and RAM.
Close the settings window and then power on the virtual machine.
总结一下 VMware Workstation 和 Fusion 中的虚拟机网络设置的选项。
VMware 产生的虚拟机会有以下几种网络模式:
虚拟机通过桥接,直接连接到物理网络。虚拟机会和主机在同一个子网中。比如你的宿主机的 IP 是 192.168.1.100,并且所在的网络中存在一个 HDCP 服务器(比如路由器等),那么虚拟机就会获得一个 192.168.1.x 的 IP 地址,表现成网络中的另外一台电脑一样。
Used to share the host’s IP address,这种模式给予了虚拟机连接到 Network Address Translation 网络的能力, 虚拟机会自动才 VMware Workstation DHCP 服务器获取一个 IP 地址,子网掩码。
这个 IP 和宿主机的网络不在同一个子网中,这个地址通过宿主机网络地址转化过。
一个和宿主机共享的私有的网络,虚拟机会被隔离在这个私有网络中,无法去访问宿主机本地网络和互联网。运行在 Host-only 网络下的虚拟机通过内部的 DHCP 服务器获取 IP 地址。你可以在这样的网络中运行一系列的虚拟机,他们之间可以网络通信。
事实上,如果禁用了和宿主机之间的网络和 DHCP,你就可以获得一个完全私有的网络。通常情况下,如果想要虚拟机访问互联网,你需要使用虚拟机的路由,比如 pfSense, VyOS 等等。
指定虚拟网络。
在 VMware Workstation 的 Edit 菜单中,可以看到 Virtual Network Editor 选项。在这个菜单中可以对虚拟网络进行管理。
在其中管理的虚拟网络,可以在虚拟机网络的 Custom 中进行使用。
LAN Segments 是 VMware Workstation 在 9 之后增加的功能。和其他网络设定不同,LAN Segments 只能通过每一个虚拟机的网络去管理。
LAN Segments 创建了一个没有 DHCP 的完全隔离的私有网络,这意味你必须给虚拟机分配一个 LAN segment。你必须要配置一个静态IP地址,或者使用自己的 DHCP 服务器。
相较于其他网络设置的好处是,你可以创建任意多个 LAN segments,并且可以指定你自己的名字来区别。这个功能在设置复杂的虚拟网络的时候尤其有用。
去年年中的时候切换到 macOS,一直用 ClashX,时隔半年又迁移回了 Linux1,发现原先使用的 V2rayL 虽然能用,但是有些简陋,并且不支持分流,并且如果一个地址失效了,还需要手动地进行切换。所以看到 Linux 的 Clash 可以自动进行流量切换的时候,就试一下。
Clash 是 Go 语言实现的,跨平台代理工具,支持 Shadowsocks/v2ray,支持规则分流等等。
可以在官方页面下载。
Linux 下载对应的 linux-amd64
即可。
在用了很长一段时间的 Clash 命令行之后,我发现 Clash For Windows 这个应用也能够在 Linux 下使用。所以最近就切换到了这个应用上。
另外欢迎订阅使用 EV Proxy 注册之后一键订阅即可使用。
下载对应的二进制,比如默认放到 ~/Downloads
目录,在终端进入该目录。
gunzip clash-linux-amd64-v0.18.0.gz
sudo mv clash-linux-amd64-v1.4.2 /usr/local/bin/clash
sudo chmod +x /usr/local/bin/clash
./clash
clash 启动后会在 ~/.config/clash
目录生成配置文件。
ls -al ~/.config/clash
.rw-r--r-- 10 einverne 23 Mar 19:30 config.yaml
.rw-r--r-- 4.0M einverne 23 Mar 19:30 Country.mmdb
比如说对于我使用的Wallless 代理,在后台复制地址之后,在网址的后面增加 &flag=clash
获取 clash 的配置文件,右击网页 Save as,选择仅网页内容,下载到本地, sub.html
。
另外还有一个代理,有兴趣的可以试用一下。
然后将查看 sub.html
内容,应该是一个 yaml 格式的文件。将此格式的文件替换默认的配置。
cat ~/Downloads/sub.html > ~/.config/clash/config.yaml
然后重新执行 /usr/local/bin/clash
。
此时检查一下配置中的 socks 端口,我一般用本地的 1080,修改一下:
socks-port: 1080
然后再运行。去浏览器中,访问 youtube.com 检查一下。
如果正常访问即完成了配置。
在配置开机启动之前,将配置文件移动到 /etc
目录:
sudo mv ~/.config/clash /etc
以后修改配置都记住修改 /etc/clash
目录下的这个配置文件。
然后使用 vi
增加 systemd 配置 sudo vi /etc/systemd/system/clash.service
放入如下内容:
[Unit]
Description=Clash Daemon
[Service]
ExecStart=/usr/local/bin/clash -d /etc/clash/
Restart=on-failure
[Install]
WantedBy=multi-user.target
启用 clash service:
sudo systemctl enable clash.service
手动启动 clash.service:
sudo systemctl start clash.service
可以使用 systemd 提供的 disable
, stop
等等命令来管理。
如果要查看 Clash service 的日志可以使用:
journalctl -e -u clash.service
如果想要将日志单独记录到文件,可以使用 systemd 的 StandardOutput
和 StandardError
将日志定向到文件中。这部分可以参考 systemd 的文档
# Works only in systemd v240 and newer!
StandardOutput=append:/var/log/clash/log.log
StandardError=append:/var/log/clash/error.log
Clash 提供了默认的 9090 端口作为远端管理端口,在配置中可以看到:
external-controller: '127.0.0.1:9090'
这样的配置。
可以使用 Clash 远程管理的页面进行管理: http://clash.razord.top/#/proxies
这个页面要求提供,Host,Port,Secret 三个输入:
其中 Secret 是在配置文件中通过:
secret: 'xxx'
进行配置的。
感谢 BobMaster 在评论里面提供其他解决方式,有兴趣可以尝试 v2rayA, 或 Qv2ray
[[Beancount]] 是一个纯文本的复式记账工具,因为是纯文本的记账工具,所以帐本就可以理解成为有一定格式的「代码」,所以编写这一份帐本,就可以和代码补充的 IDE 一样,比如在输入消费 Expenses,或者 Liabilities 等时,可以利用账户的关键字来借助插件自动补全,快速完成记账。
这篇文章重点介绍一下 VSCode 下的 Beancount 插件。
和正常的 VSCode 插件安装一样,直接在插件市场里面搜索 Beancount,找到 VSCode-Beancount,然后点击安装即可。
VSCode-Beancount 插件提供了语法高亮和账户自动补全功能。
{
"beancount.mainBeanFile": "main.bean",
"beancount.inputMethods": ["pinyin"]
}
当配置好之后,插件会自动读取 Beancount 账户信息,然后在记账的过程中,只需要通过关键字来快速输入即可。
在我使用 Beancount 的过程中,让我收益最大的是让我知道了一个词 commodity ,直接翻译为通货,它不等同于金钱,也不是我们理解的钱。但是在记账的过程中使用最多的就是以货币单位,比如 CNY 人民币,USD 美元,HKD 港币来作为 commodity 记账。
Beancount 给我普及了 commodity,它可以是用于交换的任何物品或资源,比如可以是股票,可以是黄金,也可以是期权,也可以是加密货币等。这种灵活性使得 Beancount 在处理不同类型的资产时非常强大。
每一个投资标的就是一个 commodity, 比如现金 CNY, USD, 股票 SPY, AAPL …
CNY
, USD
, CNH
, …AAPL
, GOOGL
HK_
开头按 4 位数字命名
HK_2800
, HK_0700
CN_
开头按 6 位数字命名
CN_000001
, CN_510300
, …CN_F
开头按 6 位数字命名
CN_F110011
股票交易中的「盈亏」,或者叫资本收益或损失,简称 P/L(也有缩写成 PnL,英语里面叫做 Profit and Loss)。
cost 成本价 price 最新价
2010-08-29 * "店铺" "日常消费"
Expenses:Food:Other 199.00 CNY
Assets:DebitCard:CMB -199.00 CNY
Beancount 中可以用同样的方式记录买入股票,比如以 2000 USD 买入 10 股 Google 股票,佣金 1 美元:
2020-01-01 * "购入10股谷歌"
Assets:Broker:Cash -20001.00 USD
Assets:Broker:GOOG 10 GOOG { 2000.00 USD }
Expense:Broker:Commission 1 USD
同样可以使用断言:
2020-01-02 balance Assets:Broker:GOOG 10 GOOG
卖出股票,比如
2020-08-30 * "以2500卖出2股谷歌"
Assets:Broker:GOOG -2 GOOG { 2000.00 USD } @ 2500 USD
Assets:Broker:Cash 5000 USD
Expense:Broker:Commission 1 USD
Income:Broker:PnL
单价使用 @
符号记录,总价使 @@
记录,比如下面的例子中 @@
就表示卖出一共收益。
2020-08-30 * "以2500卖出2股谷歌"
Assets:Broker:GOOG -2 GOOG { 2000.00 USD } @@ 5000 USD
Assets:Broker:Cash 5000 USD
Income:Broker:PnL
这里 Income:Broker:PnL
就是股票盈亏账户。
通过 price 可以声明价格
比如,2021-01-01 Google 的股价上升到 3000 USD
2021-01-01 price GOOG 3000 USD
待补充。
通过之前几篇文章的介绍,相信大部分人已经入门了基本的 Beancount 的使用,也能理解[[复式记账]]的魅力。
这一篇文章就接着之前的内容,来讲讲如何在 Beancount 下记录期权(或者限制性股票)交易的记账。
RSU(restricted stock units),又被称为限制性股票,restricted 意味着当前无法获得,一般经过特定的时间周期,当其成熟时才可以收到。通常的,被许诺可以在未来的 3~4 年中每个季度或每个月份收到固定份额的股票,当你离开公司的时候,剩余为成熟的份额就视为自动丢失。
其中的一种方法是,可以将 RSUs 视为 assets, 一种定期的应收款。
作者提供了一份示例。
追踪奖励
Beancount 提供了一个名为 commodity
的广义「货币」单位的概念,用户可以自定义任何类型的记账货币。相比普通的记账软件,它们可能只支持一些常见货币单位,比如人民币(CNY)或美元(USD)。但是 Beancount 的强大之处在于,你可以定义诸如 BTC 这样的单位,使得 Beancount 能够记录虚拟货币交易记录。甚至,你还可以定义 SNE 代表一股 Sony 的股票,或者 GOOG 代表一股 Google 的股票,这样就可以利用 Beancount 记录证券交易。
第一步,定义 Commodities,比如,”Hooli Inc”,最终会变成公司的流通股票,进而变成 US dollars。
1990-12-02 commodity HOOL
name: "Common shares of Hooli Inc."
quote: USD
然后定义未成熟的 RSU:
2013-01-28 commodity HOOL.UNVEST
name: "Unvested shares of Hooli from awards."
进而开设一个收入账户,比如使用 Income:US:Hooli
作为从 Hooli 的所有收入账户
2010-01-01 open Income:US:Hooli:Awards HOOL.UNVEST
然后定义一个支出账户
2014-01-28 open Expenses:Hooli:Vested HOOL.UNVEST
接受奖励
2014-04-02 * "Award S0012345"
Income:US:Hooli:Awards -1680 HOOL.UNVEST
Assets:US:Hooli:Unvested:S0012345 1680 HOOL.UNVEST
2014-04-02 open Assets:US:Hooli:Unvested:S0012345
定义一个收入账户
2013-04-04 open Income:US:Hooli:RSU
可能还需要定义其他税收的账户
2015-01-01 open Expenses:Taxes:TY2015:US:StateNY
2015-01-01 open Expenses:Taxes:TY2015:US:Federal
2015-01-01 open Expenses:Taxes:TY2015:US:SocSec
2015-01-01 open Expenses:Taxes:TY2015:US:SDI
2015-01-01 open Expenses:Taxes:TY2015:US:Medicare
2015-01-01 open Expenses:Taxes:TY2015:US:CityNYC
交完税之后会剩下的部分放入新的账户
2013-01-28 open Assets:US:Hooli:RSURefund
Vesting
2015-05-27 * "Vesting Event - S0012345 - HOOL" #award-S0012345 ^392f97dd62d0
doc: "2015-02-13.hooli.38745783.pdf"
Income:US:Hooli:RSU -4597.95 USD
Expenses:Taxes:TY2015:US:Medicare 66.68 USD
Expenses:Taxes:TY2015:US:Federal 1149.48 USD
Expenses:Taxes:TY2015:US:CityNYC 195.42 USD
Expenses:Taxes:TY2015:US:SDI 0.00 USD
Expenses:Taxes:TY2015:US:StateNY 442.32 USD
Expenses:Taxes:TY2015:US:SocSec 285.08 USD
Assets:US:Hooli:RSURefund 2458.97 USD
整个过程
;; An example that demonstrate how to track vesting of restricted stock units (RSUs).
;; See doc at: http://furius.ca/beancount/doc/vesting
1990-12-02 commodity HOOL
name: "Hooli Common shares."
2013-01-28 commodity HOOL.UNVEST
name: "Unvested award of Hooli Common shares."
2013-01-28 open Income:US:Hooli:Awards HOOL.UNVEST
2014-01-28 open Expenses:Hooli:Vested HOOL.UNVEST
2014-04-02 * "Award S0012345"
Income:US:Hooli:Awards -1680 HOOL.UNVEST
Assets:US:Hooli:Unvested:S0012345 1680 HOOL.UNVEST
2014-04-02 open Assets:US:Hooli:Unvested:S0012345
2014-07-02 * "Award C123456"
Assets:US:Hooli:Unvested:C123456 720 HOOL.UNVEST
Income:US:Hooli:Awards -720 HOOL.UNVEST
2014-07-02 open Assets:US:Hooli:Unvested:C123456
2013-04-04 open Income:US:Hooli:RSU
2015-01-01 open Expenses:Taxes:TY2015:US:StateNY
2015-01-01 open Expenses:Taxes:TY2015:US:Federal
2015-01-01 open Expenses:Taxes:TY2015:US:SocSec
2015-01-01 open Expenses:Taxes:TY2015:US:SDI
2015-01-01 open Expenses:Taxes:TY2015:US:Medicare
2015-01-01 open Expenses:Taxes:TY2015:US:CityNYC
; Rounding errors accumulate here and are paid 2-3 months after vesting
2013-01-28 open Assets:US:Hooli:RSURefund
2013-04-04 open Assets:US:Schwab:HOOL
2001-01-01 open Assets:US:BofA:Checking
2015-05-27 * "Vesting Event - S0012345 - HOOL" #award-S0012345 ^392f97dd62d0
doc: "2015-02-13.hooli.38745783.pdf"
Income:US:Hooli:RSU -4597.95 USD
Assets:US:Hooli:RSURefund 2458.97 USD
Expenses:Taxes:TY2015:US:Medicare 66.68 USD
Expenses:Taxes:TY2015:US:Federal 1149.48 USD
Expenses:Taxes:TY2015:US:CityNYC 195.42 USD
Expenses:Taxes:TY2015:US:SDI 0.00 USD
Expenses:Taxes:TY2015:US:StateNY 442.32 USD
Expenses:Taxes:TY2015:US:SocSec 285.08 USD
2015-05-27 * "Vesting Event - C123456 - HOOL" #award-C123456 ^392f97dd62d0
doc: "2015-02-13.hooli.38745783.pdf"
Income:US:Hooli:RSU -1970.55 USD
Assets:US:Hooli:RSURefund 1053.84 USD
Expenses:Taxes:TY2015:US:Medicare 28.58 USD
Expenses:Taxes:TY2015:US:Federal 492.63 USD
Expenses:Taxes:TY2015:US:CityNYC 83.75 USD
Expenses:Taxes:TY2015:US:SDI 0.00 USD
Expenses:Taxes:TY2015:US:StateNY 189.57 USD
Expenses:Taxes:TY2015:US:SocSec 122.18 USD
2015-05-25 * "Conversion into shares" ^392f97dd62d0
Assets:US:Schwab:HOOL 18 HOOL {131.3700 USD}
Assets:US:Hooli:RSURefund
Assets:US:Hooli:Unvested:S0012345 -35 HOOL.UNVEST
Expenses:Hooli:Vested 35 HOOL.UNVEST
2015-05-25 * "Conversion into shares" ^392f97dd62d0
Assets:US:Schwab:HOOL 8 HOOL {131.3700 USD}
Assets:US:Hooli:RSURefund
Assets:US:Hooli:Unvested:C123456 -15 HOOL.UNVEST
Expenses:Hooli:Vested 15 HOOL.UNVEST
2015-06-13 * "HOOLI INC PAYROLL" ^392f97dd62d0
doc: "2015-02-13.hooli.38745783.pdf"
Assets:US:Hooli:RSURefund -94.31 USD
Assets:US:Hooli:RSURefund -2.88 USD
Assets:US:BofA:Checking 97.19 USD
2015-06-14 balance Assets:US:Hooli:RSURefund 0 USD
2015-06-04 balance Assets:US:Hooli:Unvested:S0012345 1645 HOOL.UNVEST
2015-06-04 balance Assets:US:Hooli:Unvested:C123456 705 HOOL.UNVEST
2015-06-02 price HOOL.UNVEST 132.4300 USD.UNVEST
;; Example sale:
;;
;; 2013-04-04 open Assets:US:Schwab:Cash
;; 2013-04-04 open Income:US:Schwab:Gains
;;
;; 2015-09-10 * "Selling shares"
;; Assets:US:Schwab:HOOL -26 HOOL {131.3700 USD} @ 138.23 USD
;; Assets:US:Schwab:Cash 3593.98 USD
;; Income:US:Schwab:Gains
;;
;; 2015-09-11 balance Assets:US:Schwab:HOOL 0 HOOL
投资标的 Commodity
美股按照交易所代码
AAPL, SPY
港股以代号 HK_
开头,加 4 位数字
HK_2800, HK0700
A 股和场内基金,代号以 CN_
开头加 6 位数字
CN_000001
场外基金,以 CN_F
加 6 位数字
货币基金
待补充
RETE 算法是卡内基梅隆大学的 [[Charles L.Forgy]] 博士在 1974 年发表的论文中实现的算法,是一种[[模式匹配算法]]。简易版本的论文发表于 1982 年 (http://citeseer.ist.psu.edu/context/505087/0)。拉丁语的 rete 表示 ”net” 和 “network”。
这个算法设计的目的是为了在大量的规则,Objects(或者说 Facts)中寻找匹配的规则。其核心思想是通过分离的匹配项,根据内容动态的构造匹配树,缓存中间结果,以空间换取时间,降低计算量。
RETE 算法主要可以分成两个部分:
RETE 算法通过规则条件生成了一个网络,每个规则条件是网络中的一个节点。
大量模式集合和大量对象集合间比较的高效方法,通过网络筛选的方法找出所有匹配各个模式的对象和规则。
在 Dr. Forgy 1982 年的论文中,他定义了 4 种基本节点:
RETE 网络中的节点,除了根节点之外,每一个节点都对应一个 Pattern,对应规则的条件部分模式。从根节点到叶子节点定义了完整的 left-hand-side 的条件。每一个节点都保存满足这个 Pattern 的部分内存。
当一个新的 Fact 被插入或被修改时,会沿着网络传播,当满足 Pattern 时,标记节点。当一个 Fact 或者一组 Facts 满足所有 Patterns 是,就达到了叶子节点,对应的规则就被触发了。
RETE 算法设计用内存来换取执行时间。
首先来看一下 Drools 的最简单的一条规则:
rule
when
Cheese( $chedddar : name == "cheddar" )
$person : Person( favouriteCheese == $cheddar )
then
System.out.println( $person.getName() + " likes cheddar" );
end
规则中可以看到 when-then 的结构,当满足 when 中的条件时,则执行 then 语句。
可以看到条件中有两个 Fact,分别是 Cheese 和 Person。
假设有两个 Fact,Person 和 Cheese。
Alpha 网络形成一个 discrimination network,负责根据条件选择每一个独立的 WMEs。
在 discrimination network 中每一个 AlphaNode ( 1-input node)分支,
用非专业的术语来描述 discrimination network
就是一种当数据在其中传播的时候过滤数据的网络。在网络顶层的节点会有很多的匹配,当随着网络传播,会越来越少匹配。在网络的底部是 Terminal Nodes(结束节点),当走到这个节点意味着之前所有的 Pattern 都需要满足。
Alpha 网络,用来过滤 Fact,通过模式匹配找出事实集中所有符合模式的集合,Alpha 网络中包含 - ObjectTypeNode,类型节点,根节点的直接子节点,对象的类型 - Alpha Node,条件节点
Beta 网络则执行不同 WMEs 之间的 joins。这个网络中包含 2-input nodes(两个输入的节点)。每一个 Beta Node 都会将结果发送给 Beta Memory。
RETE 网络中的节点:
比如如下的 Alpha_Nodes 就表明是 Cheese( name =="cheddar", strength == "strong" )
编译的结果是规则集对应的 RETE 网络,一个 Fact 可以流动的图。
Working Memory Element,简称 WME,用于和非根节点代表的模式进行匹配的元素
当 facts 被插入到 Working Memory,引擎会为每一个 Fact 创建 Working memory elements(WMEs)。Facts 是一个 n 位元祖。
当 WME 从根节点进入 到 RETE 网络之后,根节点会将 WME 传到子节点中,然后每一个 WME 会通过网络传播下去,直到达到 Terminal Node。
1)如果 WME 的类型和根节点的后继结点 TypeNode(alpha 节点的一种)所指定的类型相同,则会将该事实保存在该 TypeNode 结点对应的 alpha 存储区中,该 WME 被传到后继结点继续匹配,否则会放弃该 WME 的后续匹配; 2)如果 WME 被传递到 alpha 节点,则会检测 WME 是否和该结点对应的模式相匹配,若匹配,则会将该事实保存在该 alpha 结点对应的存储区中,该 WME 被传递到后继结点继续匹配,否则会放弃该 WME 的后续匹配: 3)如果 WME 被传递到 beta 节点的右端,则会加入到该 beta 结点的 right 存储区,并和 left 存储区中的 Token 进行匹配(匹配动作根据 beta 结点的类型进行,例如:join,projection,selection),匹配成功,则会将该 WME 加入到 Token 中,然后将 Token 传递到下一个结点,否则会放弃该 WME 的后续匹配: 4)如果 Token 被传递到 beta 结点的左端,则会加入到该 beta 结点的 left 存储区,并和 right 存储区中的 WME 进行匹配(匹配动作根据 beta 结点的类型进行,例如:join,projection,selection),匹配成功,则该 Token 会封装匹配到的 WME 形成新的 Token,传递到下一个结点,否则会放弃该 Token 的后续匹配; 5)如果 WME 被传递到 beta 结点的左端,将 WME 封装成仅有一个 WME 元素的 WME 列表做为 Token,然后按照 4) 所示的方法进行匹配: 6)如果 Token 传递到 Terminal,则和该根结点对应的规则被激活,建立相应的 Activation,并存储到 Agenda 当中,等待激发。 7)如果 WME 被传递到 Terminal Node,将 WME 封装成仅有一个 WME 元素的 WME 列表做为 Token,然后按照 6) 所示的方法进行匹配;
特点:
不足:
建议: