Akawa

ETY001的博客

SPS的机制概述

  • 用户提交提案,提案只要有投票就算是激活了。
  • 提案的钱来自 steem.dao 账号,理论上每小时结算一次,按照投票数排序提案,顺次发钱,发完为止(因为每小时发放数额有限)。

资金来源

steem.dao 账号的资金来源于每次出块时 10% 的 steem,按照喂价中位数转化为 SBD 后存入,同时更新 dgp.sps_interval_ledger(相关逻辑在 database::process_funds() 中)。

dgp.sps_interval_ledger 会在每小时结算的时候清零(相关逻辑在 sps_processor::record_funding() 中)。

资金发放

公式一:

1
每天发放资金量 = steem.dao中的 SBD 数量 / 100 + 每日通胀

公式二:

1
当前小时发放资金 = (当前块时间戳 - 上次发放时间戳)/(24*3600) * 每天发放资金量

发放资金的时候,会按照投票数,从多到少排序所有激活的提案。

然后遍历排序好的提案,每个提案从公式二计算出的资金里发钱,直到公式二计算的资金发完为止(该逻辑在 sps_processor::transfer_payments() )。

备注1: 当前块时间戳,在区块浏览器的某个块的 timestamp 字段。
备注2: 上次发放时间戳,可以从 dgp.last_budget_time 获得。
备注3: SPS 中的通胀在当前的 HF23 版本还没有设计好,所有涉及到通胀的地方都是 0。
备注4: 公式一和公式二在 sps_processor::calculate_maintenance_budget() 中。
备注5: https://steemdb.io/block/79880772 在这个页面的 Virtual Ops 下可以看到当时那个小时的结算情况。

当前状态

目前排名第一的提案,每小时提取 24w SBD 到 steem.dao 账号,而系统每小时发放的资金大约在 1600 SBD,所以第一名的提案把钱都花完了,相当于变相停止了 SPS 系统。

但是目前排名第一的提案截止到 2029年12月31日,在其后面的还有一个截止 2030年3月1日的。这就意味着,最后这个提案可以从 2030年1月1日 到 2030年3月1日,每小时获得 1000 SBD。

在 Archlinux 下通过 snapcraft 安装了 Tradingview。但是登陆是通过浏览器网页登陆后,跳转回程序完成登陆。

而 Chrome 浏览器调用 xdg-open 打开 tradingview:// 格式的 URI 时,提示找不到程序,无法打开。

解决方法就是在 ~/.config/mimeapps.list 中,在 [Default Applications] 块里加入下面一行

1
x-scheme-handler/tradingview=tradingview_tradingview.desktop

保存退出后,可以执行下面的命令,查看是否添加成功

1
xdg-mime query default x-scheme-handler/tradingview

之后,再次登陆即可成功跳转到 Tradingview 程序。

这两天折腾 TrueNas,然后想要在 TrueNas 的虚拟机里安装 Archlinux。

但是安装完,总是无法引导启动。

搜索了很久,终于发现了一个小哥的安装视频,https://www.youtube.com/watch?v=UgkuDVaU16c&ab_channel=aespa

原来, bootloader-id 必须命名为 boot,然后 .efi 文件也必须从 grubx64.efi 手动改为 bootx64.efi

这TM不是坑爹是啥?!

最近需要在服务器上安装桌面。于是总结一下。

1
2
3
apt update && apt-get upgrade -y && \
apt install -y xubuntu-desktop && \
apt install -y xrdp

在用户家目录输出 xfce4 的 session

1
echo "xfce4-session" | tee .xsession

重启 xrdp

1
systemctl restart xrdp

Android 12及以上用户在使用Termux时,有时会显示 [Process completed (signal 9) - press Enter],这是因为Android 12的 PhantomProcesskiller 限制了应用的子进程,最大允许应用有32个子进程。

解决方案就是通过 adb 命令来修改底层的配置,命令如下:

1
2
adb shell device_config set_sync_disabled_for_tests persistent 
adb shell device_config put activity_manager max_phantom_processes 65536

这两条命令执行完,即修改最大子进程数为 65536。

补充:

可以直接在 termux 中安装 adb 工具,使用开发者工具里的无线调试来连接,并执行上面的两条指令。

1
2
3
4
5
pkg install android-tools

adb pair ip:port

adb connect ip:port

补充:

鸿蒙系统的话,执行下面的命令

1
2
adb shell /system/bin/device_config set_sync_disabled_for_tests persistent 
adb shell /system/bin/device_config put activity_manager max_phantom_processes 65536

1.安装 termux

https://github.com/termux/termux-app 下载并安装

2.打开 termux 执行下面的命令

1
2
3
4
5
$ pkg update
$ pkg upgrade
$ pkg install x11-repo proot-distro pulseaudio vim
$ pkg install termux-x11-nightly virglrenderer-android
$ proot-distro install archlinux

上面的命令是更新 termux 的包管理,安装 x11 相关工具,安装 proot,安装声音相关内容,安装 3D 相关内容,安装 archlinux。

3.进入 archlinux

1
$ proot-distro login archlinux --user root --shared-tmp

以 root 用户身份进入 archlinux,并且跟 termux 共享 /tmp

4.更换 archlinux 源(/etc/pacman.d/mirrorlist)

1
Server = https://mirrors.tuna.tsinghua.edu.cn/archlinuxarm/$arch/$repo

5.更新安装archlinux相关内容

1
2
3
# pacman -Syu
# pacman -S vim firefox networkmanager xorg xorg-server pulseaudio noto-fonts-cjk git openssh fakeroot base-devel
# pacman -S xfce4 xfce4-goodies lightdm tigervnc

6.配置密码和普通用户

1
2
3
4
# passwd
# pacman -S sudo
# useradd -m -g users -G wheel,audio,video,storage -s /bin/bash ety001
# passwd ety001

7.配置 sudo

1
2
3
# vim /etc/sudoers

ety001 ALL=(ALL:ALL) NOPASSWD: ALL

8.安装 yay

1
2
# su ety001
$ git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si

9.设置时区

1
# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

10.配置语言

修改 /etc/locale.genzh_CN.开头的注释符,并执行 locale-gen

配置默认语言

1
# echo "LANG=zh_CN.UTF-8" >> /etc/locale.conf

11.配置 vncserver

1
$ vncserver -localhost

如果是第一次启动 vncserver,会提示配置 vnc 的密码。

1
$ vncserver -kill :1

停止服务,然后访问 ~/.vnc/xstartup,注释掉所有内容后,添加下面的内容

1
startxfce4 &

这样启动 vncserver 后,会执行启动 xfce4 桌面的命令。

这里需要注意的是,在启动 vncserver 前,还需要设置下面的环境变量

1
export DISPLAY=:1

12.启动桌面

回到 termux,创建 start.sh 脚本

1
2
3
4
5
6
7
pulseaudio --start --load="module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1" --exit-idle-time=-1

pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1

virgl_test_server_android &

proot-distro login archlinux --user ety001 --shared-tmp -- bash -c "export DISPLAY=:1 PULSE_SERVER=tcp:127.0.0.1; dbus-launch --exit-with-session vncserver :1"

以后,只需要打开 termux 后,执行 start.sh 脚本即可启动 archlinux 容器和桌面。

只需要用 vnc 软件连接 127.0.0.1:5901 即可。

另外,还需要在 xfce4 的配置面板中,关闭屏保和锁屏功能。

什么是现货网格机器人

网格机器人,就是在一定的价格范围内,划定指定数量的价格网格,作为买卖价格的基础。

比如币安的 STEEM / USDT 交易对,开通一个价格范围 0.175 – 0.275 ,网格数100的机器人。那就意味着每个小网格的价格跨度是 0.001 = (0.275-0.175)/100,那么机器人建单就会按照 0.175, 0.176, 0.177, 0.178 这样的规律操作,这就是所谓的网格。

而具体的买单和卖单数量则是根据当前的市场价决定初始状态。

假设你目前开机器人订单的时候,当前市场价是 0.178,那么 0.178 之前的网格是买单,0.178之后的网格是卖单,空下 0.178 这个价格。(这里卖单需要的STEEM币,是机器人计算出需要多少初始数量的STEEM,然后以市场价一次性吃入)。

之后随着市场价格波动,机器人动态增加买卖单。比如按照上面的假设初始化以后,

Buy Sell
0.177 0.179
0.176 0.180
0.175 0.181
0.182
0.183
………

价格跌到 0.176 – 0.177 之间的时候, 0.177 的买单成交,机器人自动用 0.177 成交的 STEEM 下 0.178 的卖单,等 0.178 的卖单成交,这一个网格的低买高卖就完成了。

现货网格机器人的收益来源

  • 每个网格低买高卖的差价收益
  • 交易过程持有代币的浮盈(有浮盈就可能会有浮亏)

开设现货网格机器人需要注意的事情(干货来了)

  • 如果想要赚得多,就需要自己能判断是否在阶段性的低点。我个人经验来看,现货网格机器人更像是左侧建仓(左侧建仓的意思就是在阶段性低点的左边建仓)。浮盈应该是我们开设机器人网格单的目标。如果你想要无脑开单,那么你就只能死扛到浮盈,甚至永远也等不到浮盈(比如在 0.175 – 0.275 开网格单后,价格飙升过 0.275 后再也不回头),只能割肉结束机器人订单。
  • 选择深度不错的交易对。因为我们在开单的时候,要一次性买入代币,如果深度不好,比如你投入资金多,那么你的平均买入代币的成本就要比你预期的要高。另外深度不错,代表交易相对活跃,那么网格成交密度也会较好。
  • 过密的网格不会带来更高的收益。可能你觉得提高网格密度能提高交易频次,但是提高网格密度的同时,单个网格的收益会降低(这个在币安,火币这样的平台上,开单的时候会有预计的单个网格的收益率估算),因此如何找到一个平衡点需要自己多看多试,每个交易对的情况都各不相同,没有固定的公式。
  • 过宽的价格区间会导致资金闲置率很高,这个也需要多看多试,自己摸索。
  • 避免在牛市开现货网格机器人,尽量在熊市布局,除非你明确自己是要做短线。
  • 浮盈达到预期,尽快止盈,因为我们的最终目的还是要靠浮盈挣钱。所以在开单的时候,设置一个止盈价位是个好习惯。

总结

现货网格机器人并不是无脑就能赚钱的机器人,无论是价格低点的判断,还是各种参数的设置,都需要长时间的观察和尝试。

网格机器人只是一个辅助工具,关键还是自我对于市场价格的判断。我们可能做不到像专业的技术流的分析师那样,但是只要能判断出一个大致范围,那么就是网格机器人一展身手的时候。

关键还是自身价格判断的修炼。

真文韵输入法 是 fydeOS 团队开发的,基于 RIME 引擎,针对 ChromeOS 的输入法集成。

给中文用户第三方输入法选择方案。

但是目前还处于早期阶段,因此 UI 配置界面很简陋,可以自己通过 RIME的配置文件,按照自己的需求更改。

比如我习惯的翻页方法是逗号和句号,而这个默认不支持的。

需要我们自己修改一下配置。

在编辑 RIME 配置文件里,找到 /root/build 目录下面 yaml 配置文件,命名则是根据你安装的输入法来确定的。

打开 yaml 格式配置文件,找到 key_binder: bindings 选项,删除掉原来的 Page_DownPage_Up 配置,增加下面两行配置:

1
2
- {accept: "comma", send: Page_Down, when: paging}
- {accept: "period", send: Page_Up, when: paging}

保存后,等待输入法重载即可。

前置信息

之前两个局域网是靠 zerotier 连接的,但是 zerotier 在国内的网络环境实在是太糟糕了,即使我用了黑科技在国内服务器上搭建两 planet ,依旧是不稳定。

于是放弃 zerotier ,转而使用 wireguard 组建我的工作 VPN。

网络信息如下:

  • 局域网A: 192.168.196.0/22, 做节点的机器A的 IP: 192.168.199.81
  • 局域网B: 192.168.31.0/24, 做节点的机器B的 IP: 192.168.31.5
  • 服务器: x.x.x.x

公私钥信息如下:

  • 机器A: PubKeyA/PrivKeyA
  • 机器B: PubKeyB/PrivKeyB
  • 服务器: PubKeyServ/PrivKeyServ

公私钥生成命令:

1
wg genkey | tee privatekey | wg pubkey > publickey

步骤

1.三台机器都开启转发

1
2
# 添加下面的配置到 /etc/sysctl.conf 后执行 sysctl -p 生效
net.ipv4.ip_forward = 1

2.三台机器都安装 wireguard

3.机器A配置 /etc/wireguard/wg0.conf

1
2
3
4
5
6
7
8
9
10
11
[Interface]
PrivateKey = PrivKeyA
Address = 10.0.1.2/32
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = PubKeyServ
AllowedIPs = 10.0.1.1/32, 192.168.31.0/24
Endpoint = x.x.x.x:51820
PersistentKeepalive = 25

4.机器B配置 /etc/wireguard/wg0.conf

1
2
3
4
5
6
7
8
9
10
11
[Interface]
PrivateKey = PrivKeyB
Address = 10.0.1.3/32
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = PubKeyServ
AllowedIPs = 10.0.1.1/32, 192.168.196.0/22
Endpoint = x.x.x.x:51820
PersistentKeepalive = 25

5.服务器配置 /etc/wireguard/wg0.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Interface]
PrivateKey = PrivKeyServ
Address = 10.0.1.1/24
ListenPort = 51820
PostUp = iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE

[Peer]
# HostA
PublicKey = PubKeyA
AllowedIPs = 10.0.1.2/32, 192.168.196.0/22
PersistentKeepalive = 25

[Peer]
# HostB
PublicKey = PubKeyB
AllowedIPs = 10.0.1.3/32, 192.168.31.0/24
PersistentKeepalive = 25

6.局域网A的openwrt路由器上添加静态路由

  • 接口: lan
  • 目的地址: 192.168.31.0/24
  • 路由ip: 192.168.199.81
  • 类型: unicast

7.局域网A的openwrt路由器上添加静态路由

  • 接口: lan
  • 目的地址: 192.168.196.0/22
  • 路由ip: 192.168.31.5
  • 类型: unicast

总结

主要难点就是各个节点的 AllowedIPs 和防火墙规则配置。

Here is the demo code which displays how to create a new account with Steem JS SDK in two different ways ( by taking fee or by taking interests of claimed account).

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const steem = require('steem')

const creator = 'test1';
const activeWif = '';
const newUsername = 'test2';
const newPasswd = 'P5KZS6bp8sVxxxxxxxxxD48jwBKxshpNZxsYnJ';
const fee = '3.000 STEEM'

const newKeys = steem.auth.getPrivateKeys(newUsername, newPasswd, ['owner', 'active', 'posting', 'memo']);
console.log(newKeys);

const weightThreshold = 1;
const accountAuths = [];
const owner = {
weight_threshold: weightThreshold,
account_auths: accountAuths,
key_auths: [[newKeys.ownerPubkey, 1]],
};
const active = {
weight_threshold: weightThreshold,
account_auths: accountAuths,
key_auths: [[newKeys.activePubkey, 1]],
};
const posting = {
weight_threshold: weightThreshold,
account_auths: accountAuths,
key_auths: [[newKeys.postingPubkey, 1]],
};
const memoKey = newKeys.memoPubkey;

// create a new user by creator with 3.000 STEEM fee
steem.broadcast.accountCreate(activeWif, fee, creator, newUsername, owner, active, posting, memoKey, '{}', function(err, result) {
console.log(err, result);
});

// create a new user by creator with claimed account interests
const op = [
"create_claimed_account",
{
"creator": creator,
"new_account_name": newUsername,
"owner": owner,
"active": active,
"posting": posting,
"memo_key": memoKey,
"json_metadata": "{}"
}
];
const tx = {
operations: [op],
};
steem.broadcast.send(tx, [activeWif], function(err, result) {
console.log(err, result);
});
0%