• 粉丝日志首页

geth以太坊节点安装

比特币吸金之道系列文章,由计算机黑客发明的网络货币,无国界,无政府,无中心。没有政府滥发货币,没有通货膨胀。在全球计算机网络中,自由的实现货币兑换和流通。

本系列文章只讲程序和策略,不谈挖矿…

关于作者:

  • 张丹(Conan), 程序员/Quant: Java,R,Nodejs
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/bitcoin-install-geth

前言

以太坊(ETH)的出现开启了区块链的2.0时代,为了获得数据,最直接的方法就是搭建一个以太坊的客户端,直接从以太坊的公链上面同步账本获得数据。通过安装和运行geth,可以连接到以太坊的公链的实时网络,并进行以下操作,包括 挖掘真的以太币,在不同地址间转移资金,创建合约发送交易,探索区块历史等。

那么,让我们从搭建geth客户端节点开始吧。如果你想知道,如何使用比特币的客户端 bitcoin 获得数据,请参考文章 bitcoin比特币节点安装

目录

  1. geth安装过程
  2. 启动geth的节点

1. geth安装过程

go-ethereum客户端通常被称为geth,它是个命令行界面,执行在Go语言的运行时环境上,实现了完整以太坊节点。以太坊的官方网站地址为:https://ethereum.github.io/go-ethereum/

1.1 go的运行环境安装

由于geth是go语言开发的,在安装geth客户端之前,我们要先把go的运行环境装好。go语言的在Ubuntu的详细安装方法,请参考文章go语言安装。

下面列出go语言的简单的安装过程脚本:


# 下载最新的go包
> wget https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz

# 将下载的源码包解压至 /usr/local目录。
> tar -C /usr/local/ -xvf go1.10.3.linux-amd64.tar.gz

> 将 /usr/local/go/bin 目录添加至PATH环境变量
> export PATH=$PATH:/usr/local/go/bin

# 运行go的命令
> go
Go is a tool for managing Go source code.

Usage:

	go command [arguments]

The commands are:

	build       compile packages and dependencies
	clean       remove object files and cached files
	doc         show documentation for package or symbol
	env         print Go environment information
	bug         start a bug report
	fix         update packages to use new APIs
	fmt         gofmt (reformat) package sources
	generate    generate Go files by processing source
	get         download and install packages and dependencies
	install     compile and install packages and dependencies
	list        list packages
	run         compile and run Go program
	test        test packages
	tool        run specified go tool
	version     print Go version
	vet         report likely mistakes in packages

Use "go help [command]" for more information about a command.

Additional help topics:

	c           calling between Go and C
	buildmode   build modes
	cache       build and test caching
	filetype    file types
	gopath      GOPATH environment variable
	environment environment variables
	importpath  import path syntax
	packages    package lists
	testflag    testing flags
	testfunc    testing functions

Use "go help [topic]" for more information about that topic.

这样go的运行环境,就安装好了。

1.2 geth客户端安装

从源代码安装geth客户端的操作过程,分为以下3步:

  1. 从github下载代码库
  2. 编译geth客户端
  3. 验证geth客户端

接下来,我们就一步一步的进行操作。本文使用的Linux系统环境为:Linux Ubuntu 16.04 LTS 64bit。

1.2.1 先从geth的官方github下载代码库。

安装git的过程,就不再多说了,只需要一条命令apt install git就行了。


> git clone https://github.com/ethereum/go-ethereum.git
> cd go-ethereum

1.2.2 编译geth客户端


> make geth
build/env.sh go run build/ci.go install ./cmd/geth
>>> /usr/local/go/bin/go install -ldflags -X main.gitCommit=f1986f86f2229ea5ff587c65c9229a65f40bf591 -v ./cmd/geth
github.com/ethereum/go-ethereum/vendor/github.com/hashicorp/golang-lru/simplelru
github.com/ethereum/go-ethereum/vendor/golang.org/x/net/html/atom
github.com/ethereum/go-ethereum/vendor/golang.org/x/text/encoding/internal/identifier

// 省略

github.com/ethereum/go-ethereum/eth
github.com/ethereum/go-ethereum/les
github.com/ethereum/go-ethereum/ethstats
github.com/ethereum/go-ethereum/cmd/utils
github.com/ethereum/go-ethereum/cmd/geth
Done building.
Run "/root/go-ethereum/build/bin/geth" to launch geth.

把geth的目录,加入环境变量中。


# 将 /root/go-ethereum/build/bin 目录添加至PATH环境变量
> export PATH=$PATH:/root/go-ethereum/build/bin

1.2.3 验证geth客户端安装成功

检查geth是否安装成功,通过运行geth客户端,查看版本。


> geth version
Geth
Version: 1.8.12-unstable
Git Commit: f1986f86f2229ea5ff587c65c9229a65f40bf591
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.10.3
Operating System: linux
GOPATH=
GOROOT=/usr/local/go

这样就完成了,geth的客户端的安装。

2. 启动geth节点

安装好后,我们就可以启动geth客户端程序了,我们可以先启动以太坊公链的测试网络,增加命令行参数–testnet。


# 测试网络中启动geth
> geth --testnet console
INFO [06-20|17:15:04.991843] Maximum peer count                       ETH=25 LES=0 total=25
INFO [06-20|17:15:04.993534] Starting peer-to-peer node               instance=Geth/v1.8.12-unstable-f1986f86/linux-amd64/go1.10.3
INFO [06-20|17:15:04.993635] Allocated cache and file handles         database=/root/.ethereum/testnet/geth/chaindata cache=768 handles=512
INFO [06-20|17:15:05.054257] Writing custom genesis block 
INFO [06-20|17:15:05.069545] Persisted trie from memory database      nodes=355 size=51.89kB time=1.935374ms gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [06-20|17:15:05.070105] Initialised chain configuration          config="{ChainID: 3 Homestead: 0 DAO:  DAOSupport: true EIP150: 0 EIP155: 10 EIP158: 10 Byzantium: 1700000 Constantinople:  Engine: ethash}"
INFO [06-20|17:15:05.070282] Disk storage enabled for ethash caches   dir=/root/.ethereum/testnet/geth/ethash count=3
INFO [06-20|17:15:05.070394] Disk storage enabled for ethash DAGs     dir=/root/.ethash                       count=2
INFO [06-20|17:15:05.070531] Initialising Ethereum protocol           versions="[63 62]" network=3
INFO [06-20|17:15:05.07101] Loaded most recent local header          number=0 hash=419410…ca4a2d td=1048576
INFO [06-20|17:15:05.071186] Loaded most recent local full block      number=0 hash=419410…ca4a2d td=1048576
INFO [06-20|17:15:05.071281] Loaded most recent local fast block      number=0 hash=419410…ca4a2d td=1048576
INFO [06-20|17:15:05.071548] Regenerated local transaction journal    transactions=0 accounts=0
INFO [06-20|17:15:05.072007] Starting P2P networking 
INFO [06-20|17:15:07.258259] UDP listener up                          self=enode://652a8e7e33f87110907f31aa0943137a5252a47508f496730780fe9bdad84bc33eddc27ac2e5404f4050b1e655dc290a2106af8e4f73a5d40ac0d473e0394656@[::]:30303
INFO [06-20|17:15:07.261285] RLPx listener up                         self=enode://652a8e7e33f87110907f31aa0943137a5252a47508f496730780fe9bdad84bc33eddc27ac2e5404f4050b1e655dc290a2106af8e4f73a5d40ac0d473e0394656@[::]:30303
INFO [06-20|17:15:07.262189] IPC endpoint opened                      url=/root/.ethereum/testnet/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.12-unstable-f1986f86/linux-amd64/go1.10.3
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> 

当然,我们的目标是从以太坊公链中同步数据,接下来,关掉测试网络,我们直接启动主网。


# 启动geth客户端
> geth --datadir=/data0/eth
INFO [06-20|17:41:49.295669] Maximum peer count                       ETH=25 LES=0 total=25
INFO [06-20|17:41:49.296785] Starting peer-to-peer node               instance=Geth/v1.8.12-unstable-f1986f86/linux-amd64/go1.10.3
INFO [06-20|17:41:49.296874] Allocated cache and file handles         database=/data0/eth/geth/chaindata cache=768 handles=512
INFO [06-20|17:41:49.352014] Writing default main-net genesis block 
INFO [06-20|17:41:49.75667] Persisted trie from memory database      nodes=12356 size=1.88mB time=59.845085ms gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [06-20|17:41:49.757004] Initialised chain configuration          config="{ChainID: 1 Homestead: 1150000 DAO: 1920000 DAOSupport: true EIP150: 2463000 EIP155: 2675000 EIP158: 2675000 Byzantium: 4370000 Constantinople:  Engine: ethash}"
INFO [06-20|17:41:49.757053] Disk storage enabled for ethash caches   dir=/data0/eth/geth/ethash count=3
INFO [06-20|17:41:49.757066] Disk storage enabled for ethash DAGs     dir=/root/.ethash          count=2
INFO [06-20|17:41:49.757112] Initialising Ethereum protocol           versions="[63 62]" network=1
INFO [06-20|17:41:49.757397] Loaded most recent local header          number=0 hash=d4e567…cb8fa3 td=17179869184
INFO [06-20|17:41:49.757427] Loaded most recent local full block      number=0 hash=d4e567…cb8fa3 td=17179869184
INFO [06-20|17:41:49.757438] Loaded most recent local fast block      number=0 hash=d4e567…cb8fa3 td=17179869184
INFO [06-20|17:41:49.75756] Regenerated local transaction journal    transactions=0 accounts=0
INFO [06-20|17:41:49.757872] Starting P2P networking 
INFO [06-20|17:41:51.914746] UDP listener up                          self=enode://a42c2cfd562a0edf5ec8b647b48fa3f51639ab7a37191046578777c100022fae08976a82806def07c67c11d9b24e33aaa1e2c7a039d85803dcd78724ba2a422f@[::]:30303
INFO [06-20|17:41:51.915259] RLPx listener up                         self=enode://a42c2cfd562a0edf5ec8b647b48fa3f51639ab7a37191046578777c100022fae08976a82806def07c67c11d9b24e33aaa1e2c7a039d85803dcd78724ba2a422f@[::]:30303
INFO [06-20|17:41:51.918433] IPC endpoint opened                      url=/data0/eth/geth.ipc
INFO [06-20|17:42:01.916843] Block synchronisation started 
INFO [06-20|17:42:04.015969] Imported new block headers               count=192 elapsed=1.016s number=192 hash=723899…123390 ignored=0
INFO [06-20|17:42:04.032948] Imported new block receipts              count=2   elapsed=168.99µs number=2   hash=b495a1…4698c9 size=8.00B  ignored=0
INFO [06-20|17:42:04.087556] Imported new block headers               count=192 elapsed=68.154ms number=384 hash=d3d5d5…c79cf3 ignored=0

启动参数:

  • –datadir,用于指定目录

接下来,进入/data0/eth的指定目录。


> cd /data0/eth
> ll
total 16
drwxr-xr-x 4 root root 4096 Jun 20 17:43 ./
drwxr-xr-x 5 root root 4096 Jun 20 17:41 ../
drwx------ 5 root root 4096 Jun 20 17:43 geth/
srw------- 1 root root    0 Jun 20 17:43 geth.ipc=
drwx------ 2 root root 4096 Jun 20 17:41 keystore/

有2个文件夹,分别存入不同的文件:

  • geth, 用于存储公链的数据
  • keystore, 用于存储秘钥
  • geth.ipc=, 启动时产生一个文件

接下来,我们打开一个命令工作台


> geth --datadir=/data0/eth attach
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.12-unstable-f1986f86/linux-amd64/go1.10.3
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

# 输入eth命令
> eth
{
  accounts: [],
  blockNumber: 0,
  coinbase: undefined,
  compile: {
    lll: function(),
    serpent: function(),
    solidity: function()
  },
  defaultAccount: undefined,
  defaultBlock: "latest",
  gasPrice: 18000000000,
  hashrate: 0,
  mining: false,
  pendingTransactions: [],
  protocolVersion: "0x3f",
  syncing: {
    currentBlock: 1841355,
    highestBlock: 5822416,
    knownStates: 4513217,
    pulledStates: 4491604,
    startingBlock: 1628922
  },
  call: function(),
  contract: function(abi),
  estimateGas: function(),
  filter: function(options, callback, filterCreationErrorCallback),
  getAccounts: function(callback),
  getBalance: function(),
  getBlock: function(),
  getBlockNumber: function(callback),
  getBlockTransactionCount: function(),
  getBlockUncleCount: function(),
  getCode: function(),
  getCoinbase: function(callback),
  getCompilers: function(),
  getGasPrice: function(callback),
  getHashrate: function(callback),
  getMining: function(callback),
  getPendingTransactions: function(callback),
  getProtocolVersion: function(callback),
  getRawTransaction: function(),
  getRawTransactionFromBlock: function(),
  getStorageAt: function(),
  getSyncing: function(callback),
  getTransaction: function(),
  getTransactionCount: function(),
  getTransactionFromBlock: function(),
  getTransactionReceipt: function(),
  getUncle: function(),
  getWork: function(),
  iban: function(iban),
  icapNamereg: function(),
  isSyncing: function(callback),
  namereg: function(),
  resend: function(),
  sendIBANTransaction: function(),
  sendRawTransaction: function(),
  sendTransaction: function(),
  sign: function(),
  signTransaction: function(),
  submitTransaction: function(),
  submitWork: function()
}

新建一个账户,test.dan


# 查看我的账户 
> eth.accounts
[]

# 新建一个账户
> personal.newAccount("test.dan")
"0x377410e6b50762a51d54d9f26830e60124072f35"

# 再查看我的账户
> eth.accounts
["0x377410e6b50762a51d54d9f26830e60124072f35"]

# 查看账号余额
> eth.getBalance(eth.accounts[0])
0

同时,我们也可以直接通过etherscan,以太坊的区块浏览器来查询这个新建的账号的情况。

从网页上,我们可以看到这个地址已经生效,只是没有金额。看到这些信息,代表你的geth程序已经启动了。有几十G的数据,需要同步!

安装geth相比bitcoin安装复杂度差不多,按照官方文档的介绍基本能走通的,安装过程对于技术人来不是什么大问题。不同的公链,有不同的节点软件,安装方法也不同,下一篇文章将介绍EOS的客户端EOSIO的安装。

转载请注明出处:
http://blog.fens.me/bitcoin-install-geth

打赏作者

bitcoin比特币节点安装

比特币吸金之道系列文章,由计算机黑客发明的网络货币,无国界,无政府,无中心。没有政府滥发货币,没有通货膨胀。在全球计算机网络中,自由的实现货币兑换和流通。

本系列文章只讲程序和策略,不谈挖矿…

关于作者:

  • 张丹(Conan), 程序员/Quant: Java,R,Nodejs
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/bitcoin-install

前言

量化交易的第一步就是获取数据,那么获得比特币的数据,最直接的方法就是搭建一个比特币的客户端,直接从比特币的公链上面同步账本获得数据。比特币网络的构建基础,是基于无中心节点和透明化,这样每个节点都会获得比特币网络中的全量数据。

那么,先我们从搭建bitcoin客户端节点开始吧。

目录

  1. bitcoin安装过程
  2. 启动bitcoin的节点

1. bitcoin安装过程

从源代码安装bitcoin客户端的操作过程,分为以下7步:

  1. 从github下载代码库
  2. 切换最新的版本
  3. 安装系统依赖库
  4. 运行autogen.sh脚本
  5. 运行configure脚本
  6. 运行make和make install
  7. 验证bitcoin安装成功

接下来,我们就一步一步的进行操作。本文使用的Linux系统环境为:Linux Ubuntu 16.04 LTS 64bit。

1.1 先从bitcoin的官方github下载代码库。

安装git的过程,就不再多说了,只需要一条命令apt install git就行了。


> git clone https://github.com/bitcoin/bitcoin.git
> cd bitcoin

1.2 找到最新的tag版本为v0.16.0。


> git tag
noversion
v0.1.5
...
v0.16.0
v0.16.0rc1
v0.16.0rc2
v0.16.0rc3
v0.16.0rc4
v0.2.0
...
v0.9.3
v0.9.3rc1
v0.9.3rc2
v0.9.4
v0.9.5
v0.9.5rc1
v0.9.5rc2

切换到最新版本的分支。


> git checkout v0.16.0

1.3 安装需要依赖的系统工具,这里会用到Libtool、pkg-config、libboost、libdb工具包,需要提前安装。


> apt install libtool
> apt install pkg-config
> apt install libboost-all-dev
> apt install libdb5.3++-dev 
> apt install libevent-dev

1.4 用./autogen.sh脚本进行编译,


> ./autogen.sh 

1.5 运行configure脚本

执行完成后,发现当前目标生了configure文件,然后运行configure文件。运行时,会出现一个BerkerlyDB的错误,它指定要求装4.8版本的BerkerlyDB。解决方法有2种,第1种,去下载对应版本的BerkerlyDB;第二种,跳过这一步的检查。我们先用第2种方法,跳过BerkeleyDB的兼容性检查。


> ./configure
configure: error: Found Berkeley DB other than 4.8, required for portable wallets (--with-incompatible-bdb to ignore or --disable-wallet to disable wallet functionality)

# 跳过BerkeleyDB的兼容性检查
> ./configure --with-incompatible-bdb

1.6 执行make和make install。


> make 
> make install

1.7 验证bitcoin安装成功

验证bitcoin安装成功,有2个命令 bitcoin-cli和bitcoind。我们需要检查一下,是否这个启动命令,安装到在系统环境中。

  • bitcoind,用于启动bitcoin的节点,同步账本数据。
  • bitcoin-cli,用于与bitcoind节点通信。

查看启动命令的系统安装位置。


> which bitcoin-cli
/usr/local/bin/bitcoin-cli

> which bitcoind
/usr/local/bin/bitcoind

分别查看bitcoind 和 bitcoin-cli 命令的帮助信息。


> bitcoind -help
> bitcoin-cli -help

这样就完成了,bitcoin的客户端的安装。

2. 启动bitcoin节点

通过bitcoind命令启动bitcoin的核心客户端程序。运行前,我先要定义一个bitcoin.conf的配置文件,用于设置RPC-JSON的访问用户。

新建配置文件 .bitcoin/bitcoin.conf。设置rpc用户的账号和密码,请大家按照复杂密码设定要求设置。官方推荐的bitcoin.conf文件的配置项,打开文件


> vi .bitcoin/bitcoin.conf

rpcuser=bsspirit
rpcpassword=98jfidayelqlvjieJDIjda

启动bitcoind服务端,并把数据写入到/data/btc目录,在控制台打印输出。


> bitcoind -datadir=/data/btc -conf=/root/.bitcoin/bitcoin.conf -printtoconsole

2018-05-30 01:51:06 Bitcoin Core version v0.16.0 (release build)
2018-05-30 01:51:06 InitParameterInteraction: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1
2018-05-30 01:51:06 Assuming ancestors of block 0000000000000000005214481d2d96f898e3d5416e43359c145944a909d242e0 have valid signatures.
2018-05-30 01:51:06 Setting nMinimumChainWork=000000000000000000000000000000000000000000f91c579d57cad4bc5278cc
2018-05-30 01:51:06 Using the 'sse4' SHA256 implementation
2018-05-30 01:51:06 Using RdRand as an additional entropy source
2018-05-30 01:51:06 Default data directory /root/.bitcoin
2018-05-30 01:51:06 Using data directory /data/btc
2018-05-30 01:51:06 Using config file /root/.bitcoin/bitcoin.conf
2018-05-30 01:51:06 Using at most 125 automatic connections (1024 file descriptors available)
2018-05-30 01:51:06 Using 16 MiB out of 32/2 requested for signature cache, able to store 524288 elements
2018-05-30 01:51:06 Using 16 MiB out of 32/2 requested for script execution cache, able to store 524288 elements
2018-05-30 01:51:06 Using 4 threads for script verification
2018-05-30 01:51:06 scheduler thread start
2018-05-30 01:51:06 HTTP: creating work queue of depth 16
2018-05-30 01:51:06 Config options rpcuser and rpcpassword will soon be deprecated. Locally-run instances may remove rpcuser to use cookie-based auth, or may be replaced with rpcauth. Please see share/rpcuser for rpcauth auth generation.
2018-05-30 01:51:06 HTTP: starting 4 worker threads
2018-05-30 01:51:06 Using wallet directory /data/btc
2018-05-30 01:51:06 init message: Verifying wallet(s)...
2018-05-30 01:51:06 Using BerkeleyDB version Berkeley DB 5.3.28: (September  9, 2013)
2018-05-30 01:51:06 Using wallet wallet.dat
2018-05-30 01:51:06 CDBEnv::Open: LogDir=/data/btc/database ErrorFile=/data/btc/db.log
2018-05-30 01:51:06 Cache configuration:
2018-05-30 01:51:06 * Using 2.0MiB for block index database
2018-05-30 01:51:06 * Using 8.0MiB for chain state database
2018-05-30 01:51:06 * Using 440.0MiB for in-memory UTXO set (plus up to 286.1MiB of unused mempool space)
2018-05-30 01:51:06 init message: Loading block index...
2018-05-30 01:51:06 Opening LevelDB in /data/btc/blocks/index
2018-05-30 01:51:07 Opened LevelDB successfully
2018-05-30 01:51:07 Using obfuscation key for /data/btc/blocks/index: 0000000000000000
2018-05-30 01:51:08 LoadBlockIndexDB: last block file = 0
2018-05-30 01:51:08 LoadBlockIndexDB: last block file info: CBlockFileInfo(blocks=1, size=293, heights=0...0, time=2009-01-03...2009-01-03)
2018-05-30 01:51:08 Checking all blk files are present...
2018-05-30 01:51:08 LoadBlockIndexDB: transaction index disabled
2018-05-30 01:51:08 Opening LevelDB in /data/btc/chainstate
2018-05-30 01:51:08 Opened LevelDB successfully
2018-05-30 01:51:08 Using obfuscation key for /data/btc/chainstate: 6adad0af82f188f1
2018-05-30 01:51:08 Loaded best chain: hashBestChain=000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f height=0 date=2009-01-03 18:15:05 progress=0.000000
2018-05-30 01:51:08 init message: Rewinding blocks...
2018-05-30 01:51:09 init message: Verifying blocks...
2018-05-30 01:51:09  block index            2369ms
2018-05-30 01:51:09 init message: Loading wallet...
2018-05-30 01:51:09 nFileVersion = 160000
2018-05-30 01:51:09 Keys: 2001 plaintext, 0 encrypted, 2001 w/ metadata, 2001 total
2018-05-30 01:51:09  wallet                   67ms
2018-05-30 01:51:09 setKeyPool.size() = 2000
2018-05-30 01:51:09 mapWallet.size() = 0
2018-05-30 01:51:09 mapAddressBook.size() = 0
2018-05-30 01:51:09 mapBlockIndex.size() = 279999
2018-05-30 01:51:09 nBestHeight = 0
2018-05-30 01:51:09 Imported mempool transactions from disk: 0 succeeded, 0 failed, 0 expired, 0 already there
2018-05-30 01:51:09 AddLocal(103.211.167.71:8333,1)
2018-05-30 01:51:09 Discover: IPv4 eth0: 103.211.167.71
2018-05-30 01:51:09 Bound to [::]:8333
2018-05-30 01:51:09 Bound to 0.0.0.0:8333
2018-05-30 01:51:09 init message: Loading P2P addresses...
2018-05-30 01:51:09 torcontrol thread start
2018-05-30 01:51:09 Loaded 2445 addresses from peers.dat  9ms
2018-05-30 01:51:09 init message: Loading banlist...
2018-05-30 01:51:09 init message: Starting network threads...
2018-05-30 01:51:09 dnsseed thread start
2018-05-30 01:51:09 net thread start
2018-05-30 01:51:09 addcon thread start
2018-05-30 01:51:09 init message: Done loading
2018-05-30 01:51:09 opencon thread start
2018-05-30 01:51:09 msghand thread start
2018-05-30 01:51:09 New outbound peer connected: version: 70015, blocks=525031, peer=0
2018-05-30 01:51:11 New outbound peer connected: version: 70015, blocks=525031, peer=1

....

启动参数:

  • -datadir,用于指定目录
  • -conf,用于指定配置文件
  • -printtoconsole,用于控制台输出

如果打算后台执行,可以增加-daemon参数。同时,去掉-printtoconsole参数,在后面的日志文件中,进行输出。


> bitcoind -datadir=/data/btc -conf=/root/.bitcoin/bitcoin.conf -daemon
Bitcoin server starting

# 查看日志,在数据输出的目录,跟踪debug.log文件。
> tail -f /data/btc/debug.log 
11-04-11 22:01:50' progress=0.001211 cache=23.8MiB(165438txo)
2018-05-30 04:21:12 UpdateTip: new best=00000000000044640cb1d3e034f8df6604d1ac1346e6162bfca8dc60c4bbd887 height=117873 version=0x00000001 log2_work=61.645341 tx=403428 date='2011-04-11 22:02:29' progress=0.001212 cache=23.8MiB(165441txo)
2018-05-30 04:21:12 UpdateTip: new best=0000000000006488914c16dc226f1d73d5dcd6c258c3bc926fa0f804909dbd1b height=117874 version=0x00000001 log2_work=61.645483 tx=403445 date='2011-04-11 22:19:06' progress=0.001212 cache=23.8MiB(165459txo)
2018-05-30 04:21:12 UpdateTip: new best=000000000000988f65c0d5b018241f0dd13ea6b73c6228efccbbb577b5791f06 height=117875 version=0x00000001 log2_work=61.645624 tx=403453 date='2011-04-11 22:21:40' progress=0.001212 cache=23.8MiB(165460txo)

...

运行bitcoin-cli getblockchaininfo 命令,显示关于比特币网络节点、钱包、区块链数据库状态的基础信息。


> bitcoin-cli getblockchaininfo
{
  "chain": "main",
  "blocks": 2867,
  "headers": 525050,
  "bestblockhash": "000000006d6af482c12555a44bed3a0d4bbadf0fa27274225a1ed808b8a7d405",
  "difficulty": 1,
  "mediantime": 1233666084,
  "verificationprogress": 8.75401245716694e-06,
  "initialblockdownload": true,
  "chainwork": "00000000000000000000000000000000000000000000000000000b340b340b34",
  "size_on_disk": 852350,
  "pruned": false,
  "softforks": [
    {
      "id": "bip34",
      "version": 2,
      "reject": {
        "status": false
      }
    },
    {
      "id": "bip66",
      "version": 3,
      "reject": {
        "status": false
      }
    },
    {
      "id": "bip65",
      "version": 4,
      "reject": {
        "status": false
      }
    }
  ],
  "bip9_softforks": {
    "csv": {
      "status": "defined",
      "startTime": 1462060800,
      "timeout": 1493596800,
      "since": 0
    },
    "segwit": {
      "status": "defined",
      "startTime": 1479168000,
      "timeout": 1510704000,
      "since": 0
    }
  },
  "warnings": ""
}

看到这些信息,代表你的bitcoin程序已经启动了。有几十G的数据,需要同步!

安装bitcoin相比用apt安装要复杂一些,不过按照官方文档的介绍基本能走通的,安装过程对于技术人来不是什么大问题。不同的公链,有不同的节点软件,安装方法也不同,下一篇文章将介绍以太坊的客户端Geth的安装

转载请注明出处:
http://blog.fens.me/bitcoin-install

打赏作者

miniCRAN离线安装R的依赖库

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹(Conan), 程序员Java,R,Nodejs
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-install-offline

前言

最近经常去有网络隔离的机构,每次安装R语言的环境都是特别痛苦的经历。物理网络完全隔绝,不能通过互联网进行R语言的安装,只能预先下载所有软件,再进行安装。

对于有众多依赖的库,安装过程就变得很复杂了。无意中,发现了一个可以找到每个包的依赖包的库miniCRAN,让这个安装包过程,变得自动化一点。

目录

  1. 离线安装R的依赖库的过程
  2. miniCRAN介绍
  3. 5分钟上手
  4. miniCRAN包的函数介绍
  5. miniCRAN的使用方法

1. 离线安装R的依赖库的过程

对于物理网络完全被隔绝的情况,我们不能通过互联网进行R语言的安装,只能预先下载所有软件,再进行安装。

操作过程包括以下几步操作:

  1. 在有网的环境中,下载系统软件,比例 windows环境要下载对应的.net framework。
  2. 在有网的环境中,下载R语言软件。
  3. 在有网的环境中,下载第三方软件包,比如xts包。
  4. 在有网的环境中,用miniCRAN找到xts包,所有的依赖包。
  5. 在有网的环境中,下载所有的依赖包。
  6. 通过U盘或者其他的方式,复制到无网的环境中。
  7. 分别安装系统软件,R语言软件,依赖包,软件包。
  8. 重复以上过程,直到把软件都安装好。

以上操作过程中,最复杂的操作就在于找到所有的依赖包。

2. miniCRAN介绍

miniCRAN包,主要用于发现软件包的依赖关系。R语言中,每个包一般都其所依赖的扩展包,对于企业或者机构内网来说,由于防火墙或者基于安全的管理规则,不允许从互联网下载安装。那么,用户就需要从CRAN中,下载对应的软件包,一个一个安装。通过miniCRAN包,可以递归读取这些软件包的依赖关系,然后就可以下载这些依赖包了。

开发环境所使用的系统环境

  • Win10 64bit
  • R: 3.2.3 x86_64-w64-mingw32/x64 b4bit

miniCRAN包的安装比较简单,直接用install.pacakges()函数就行。


> install.packages("miniCRAN")
         binary source needs_compilation
miniCRAN  0.2.7 0.2.11             FALSE

installing the source package 'miniCRAN'

URLhttp://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib/miniCRAN_0.2.11.tar.gz'
Content type 'application/octet-stream' length 4114313 bytes (3.9 MB)
downloaded 3.9 MB

* installing *source* package 'miniCRAN' ...
** 'miniCRAN'MD5
** R
** data
*** moving datasets to lazyload DB
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded
*** arch - i386
*** arch - x64
* DONE (miniCRAN)

3. 5分钟上手

我们先做一个小的测试,分析一下chron包如果本地安装,都需要使用哪些包,会有哪些依赖关系。我们打开CRAN上面的,官方项目网页,https://cran.r-project.org/web/packages/xts/

xts唯一强依赖的包(depends)是zoo,引用R系统包methods,同时建议安装timeSeries, timeDate, tSeries, chron, fts, tis, RUnit包。

接下来,我们通过miniCRAN找到xts包的依赖关系。


> library(miniCRAN)
> tags <- "xts"
> pkgDep(tags, availPkgs = cranJuly2014)
 [1] "xts"          "zoo"          "lattice"     
 [4] "timeDate"     "quadprog"     "Hmisc"       
 [7] "survival"     "Formula"      "latticeExtra"
[10] "cluster"      "RColorBrewer" "BH"          
[13] "timeSeries"   "tseries"      "its"         
[16] "chron"        "fts"          "tis"    

画出依赖关系图。


> dg <- makeDepGraph(tags, enhances = TRUE, availPkgs = cranJuly2014)
> plot(dg, legendPosition = c(-1, 1), vertex.size = 20)

从图中,可以把整个的依赖关系看得很清楚了。

4. miniCRAN包的函数介绍

整个miniCRAN包大概有20多个函数,其中最有用的函数就是pkgDeg()和pkgAvail()。

4.1 pkgDeg()函数

pkgDeg()函数,主要对Depends,Imports和LinkLibrary执行递归检索,对Suggests执行非递归检索。


pkgDep(pkg, availPkgs, repos = getOption("repos"), type = "source",
  depends = TRUE, suggests = TRUE, enhances = FALSE,
  includeBasePkgs = FALSE, Rversion = R.version, quiet = FALSE, ...)

参数解读:

  • pkg: 包名
  • availPkgs: 所有包列表
  • repos: CRAN软件源
  • type: 下载类型,源代或二进制
  • depends: 依赖关系,包括Depends, Imports, LinkingTo
  • suggests: 建议关系
  • enhances: 增强关系
  • includeBasePkgs: 是否包括R base包
  • Rversion: R版本

4.2 pkgAvail()函数

pkgAvail()函数,是对 available.packages()函数的一个封装。如果提供了参数路径,那么该函数将尝试从本地存储库读取数据,否则尝试从repos url的CRAN镜像读取数据。


pkgAvail(repos = getOption("repos"), type = "source",
  Rversion = R.version, quiet = FALSE)

参数解读:

  • repos: CRAN软件源
  • type: 下载类型,源代或二进制
  • Rversion: R版本

这个函数在我目前测试的版本中,有一些bug,可以用available.packages()函数来解决。

5. miniCRAN的使用方法

接下来,我们详细地介绍一下,找到某包的依赖的使用方法。

5.1 定义软件源

如果我们用install.packages()函数安装过软件包,在你的本地配置中,会有当前的软件源,那么我们可以用getOption()函数,来获得本地的软件源。


> repos<-getOption("repos")
> repos
                                        CRAN 
"https://mirrors.tuna.tsinghua.edu.cn/CRAN/" 
                                   CRANextra 
        "http://www.stats.ox.ac.uk/pub/RWin" 
attr(,"RStudio")
[1] TRUE

我当前环境中配置的CRAN软件源为 https://mirrors.tuna.tsinghua.edu.cn/CRAN/ 。

5.2 获得软件源的包列表

通过软件源URL,我们需要获得软件源的包列表。


> curl<-contrib.url(repos)
> aps<-available.packages(curl)

> head(aps)
            Package       Version Priority Depends                                               Imports                                  LinkingTo
A3          "A3"          "1.0.0" NA       "R (>= 2.15.0), xtable, pbapply"                      NA                                       NA       
abbyyR      "abbyyR"      "0.5.1" NA       "R (>= 3.2.0)"                                        "httr, XML, curl, readr, plyr, progress" NA       
abc         "abc"         "2.1"   NA       "R (>= 2.10), abc.data, nnet, quantreg, MASS, locfit" NA                                       NA       
ABCanalysis "ABCanalysis" "1.2.1" NA       "R (>= 2.10)"                                         "plotrix"                                NA       
abc.data    "abc.data"    "1.0"   NA       "R (>= 2.10)"                                         NA                                       NA       
abcdeFBA    "abcdeFBA"    "0.4"   NA       "Rglpk,rgl,corrplot,lattice,R (>= 2.10)"              NA                                       NA       
            Suggests                               Enhances License              License_is_FOSS License_restricts_use OS_type Archs MD5sum
A3          "randomForest, e1071"                  NA       "GPL (>= 2)"         NA              NA                    NA      NA    NA    
abbyyR      "testthat, rmarkdown, knitr (>= 1.11)" NA       "MIT + file LICENSE" NA              NA                    NA      NA    NA    
abc         NA                                     NA       "GPL (>= 3)"         NA              NA                    NA      NA    NA    
ABCanalysis NA                                     NA       "GPL-3"              NA              NA                    NA      NA    NA    
abc.data    NA                                     NA       "GPL (>= 3)"         NA              NA                    NA      NA    NA    
abcdeFBA    "LIM,sybil"                            NA       "GPL-2"              NA              NA                    NA      NA    NA    
            NeedsCompilation File Repository                                             
A3          "no"             NA   "https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib"
abbyyR      "no"             NA   "https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib"
abc         "no"             NA   "https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib"
ABCanalysis "no"             NA   "https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib"
abc.data    "no"             NA   "https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib"
abcdeFBA    "no"             NA   "https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib"

取出xts包所对应的配置信息。


> aps[which(row.names(aps)=='xts'),]
                                                Package                                                 Version 
                                                  "xts"                                                "0.10-2" 
                                               Priority                                                 Depends 
                                                     NA                                       "zoo (>= 1.7-12)" 
                                                Imports                                               LinkingTo 
                                              "methods"                                                   "zoo" 
                                               Suggests                                                Enhances 
"timeSeries, timeDate, tseries, chron, fts, tis, RUnit"                                                      NA 
                                                License                                         License_is_FOSS 
                                           "GPL (>= 2)"                                                      NA 
                                  License_restricts_use                                                 OS_type 
                                                     NA                                                      NA 
                                                  Archs                                                  MD5sum 
                                                     NA                                                      NA 
                                       NeedsCompilation                                                    File 
                                                  "yes"                                                      NA 
                                             Repository 
"https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/contrib" 

5.3 找到依赖包的列表

从所有的软件包中,找到对应软件依赖包的列表。


# 要找到xts和TTR软件的依赖包
> libs<-c("xts","TTR")
> pkgList<-pkgDep(pkg=libs,availPkgs=aps,repos=repos)
> pkgList
 [1] "xts"        "TTR"        "zoo"        "lattice"    "curl"       "timeDate"   "quadprog"  
 [8] "quantmod"   "BH"         "timeSeries" "tseries"    "chron"      "fts"        "tis"       
[15] "RUnit"     

5.4 下载所有依赖包

运行下载函数,下载所有的依赖包。


> dp<-download.packages(pkgList,"D:/workspace/R/miniCRAN/pgk",type=getOption("pkgType"))
> dp
      [,1]         [,2]                                                    
 [1,] "xts"        "D:/workspace/R/miniCRAN/pgk/xts_0.10-2.tar.gz"         
 [2,] "TTR"        "D:/workspace/R/miniCRAN/pgk/TTR_0.23-3.tar.gz"         
 [3,] "zoo"        "D:/workspace/R/miniCRAN/pgk/zoo_1.8-1.tar.gz"          
 [4,] "lattice"    "D:/workspace/R/miniCRAN/pgk/lattice_0.20-35.tar.gz"    
 [5,] "curl"       "D:/workspace/R/miniCRAN/pgk/curl_3.2.tar.gz"           
 [6,] "timeDate"   "D:/workspace/R/miniCRAN/pgk/timeDate_3043.102.tar.gz"  
 [7,] "quadprog"   "D:/workspace/R/miniCRAN/pgk/quadprog_1.5-5.tar.gz"     
 [8,] "quantmod"   "D:/workspace/R/miniCRAN/pgk/quantmod_0.4-13.tar.gz"    
 [9,] "BH"         "D:/workspace/R/miniCRAN/pgk/BH_1.66.0-1.tar.gz"        
[10,] "timeSeries" "D:/workspace/R/miniCRAN/pgk/timeSeries_3042.102.tar.gz"
[11,] "tseries"    "D:/workspace/R/miniCRAN/pgk/tseries_0.10-44.tar.gz"    
[12,] "chron"      "D:/workspace/R/miniCRAN/pgk/chron_2.3-52.tar.gz"       
[13,] "fts"        "D:/workspace/R/miniCRAN/pgk/fts_0.9.9.tar.gz"          
[14,] "tis"        "D:/workspace/R/miniCRAN/pgk/tis_1.34.tar.gz"           
[15,] "RUnit"      "D:/workspace/R/miniCRAN/pgk/RUnit_0.4.31.tar.gz"       

本地目录查看下载的文件。


> dir("D:/workspace/R/miniCRAN/pgk")
 [1] "BH_1.66.0-1.tar.gz"         "chron_2.3-52.tar.gz"        "curl_3.2.tar.gz"           
 [4] "fts_0.9.9.tar.gz"           "lattice_0.20-35.tar.gz"     "quadprog_1.5-5.tar.gz"     
 [7] "quantmod_0.4-13.tar.gz"     "RUnit_0.4.31.tar.gz"        "timeDate_3043.102.tar.gz"  
[10] "timeSeries_3042.102.tar.gz" "tis_1.34.tar.gz"            "tseries_0.10-44.tar.gz"    
[13] "TTR_0.23-3.tar.gz"          "xts_0.10-2.tar.gz"          "zoo_1.8-1.tar.gz"  

5.5 安装软件包

用R语言的函数,进行本地安装。


> install.packages(dp[,2], repos = NULL, type="source")

另外,我们也可以用命令行,进行安装。


> R CMD INSTALL D:\workspace\R\miniCRAN\pgk\zoo_1.8-1.tar.gz

通过使用miniCRAN包,就让我们找到依赖包的这事情,变得简单多了。再通过批量的离线下载,和批量的安装,就可以让我们的操作更有效率。不然,一个一包的安装,真是要把人给逼疯了!

虽然本文讲了通用的方法,但对于有一些包安装过程中,还需要从网上再下载其他的包,还需要具体问题具体分析,手动安装依赖包的过程,确实是无比复杂的。

转载请注明出处:
http://blog.fens.me/r-install-offline

打赏作者

宽客挑战赛: 量化投资基础知识12题

跨界知识聚会系列文章,“知识是用来分享和传承的”,各种会议、论坛、沙龙都是分享知识的绝佳场所。我也有幸作为演讲嘉宾参加了一些国内的大型会议,向大家展示我所做的一些成果。从听众到演讲感觉是不一样的,把知识分享出来,你才能收获更多。

关于作者:

  • 张丹(Conan), 程序员R,Nodejs,Java
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/meeting-quant-20180315

前言

本次与“量化投资与机器学习”微信公众号合作,进行宽客挑战赛(第二期)!我来出题,大家大回答!

这期的挑战有点难度哦,全答对算你厉害!!

目录

  1. 答题规则
  2. 答题开始
  3. 公布答案
  4. 获奖名单

1. 答题规则

本次与“量化投资与机器学习”微信公众号合作,进行宽客挑战赛(第二期),答题页的链接

参与规则

  1. 请点击文末写留言,将答案发送至后台。
  2. 我们会根据后台用户提交答案的时间顺序,选出全部回答正确的前5位用户,并免费赠送这本丛书。
  3. 我们会在2017.03.19—07点公布答案(第一条置顶留言)

本次奖励,我的新书:《R的极客理想:量化投资篇》



2. 答题开始

1、black-litterman 的统计学算法基础是?

a. 均值方差模型

b. 贝叶斯模型

c. arima模型

d. 神经网络

2、哪个包是R语言中,用于计算技术指标的?

a. xts

b. WindR

c. quantmod

d. TTR

3、基于APT理论进行配对交易时,错误配对方法是?

a. 沪深300指数基金,IF股指期货合约

b. 铜CU1804合约,铜CU1805合约

c. A股工商银行,H股工商银行

d. 国债指数,回购GC001

4、可转债的负溢价率套利,正确的描述是?

a. 正股价格大于可转债价格

b. 正股价格小于可转债价格

c, 转股价值大于可转债价格

d, 转股价值小于可转债价格

5、2个人a和b合伙投资炒股,开始各入金50w股权各占50%,6个月后赚了50w,b继续追加投资60w,问a和b的股权比例?

a. a:b=5:12

b. a:b=5:11

c. a:b=5:9

d. a:b=5:7

6、对线性回归模型进行调优进时,不需要看指标是?

a. AIC

b. ROC

c. p-value

d. R-squared

7、某只指数跟踪的量化基金,其beta合理取值为?

a. 0.5

b. 1

c. 1.5

d. 2

8、期货交易时,人为降杠杠的方法是?

a. 用现货对冲

b. 只用1/n的资金交易,留有大部分现金,n为杠杠倍数

c. 同时开多单和空单,双向操作

d. 要求期货公司开通不加杠杠的通道

9、股票分红时,10派10转10,错误的描述是?

a. 转10,是指公司用资本公积金对于股东每10股转增10股。

b. 派10,是指公司用未分配利润每10股现金分红10元。

c. 你有100股,分红后,你将变成200股和100元现金

d. 分红后,股票价格会下降

10、用机器学习的方法建模,回测很好为什么实盘会不好?

a. 过拟合

b. 未来函数

c. 滑点

d. 以上都有可能

11、假设赌局: 你赢的概率是60%,下注1元,赢时可获得2元,输时下注的1元就没了。你的本金是100元,赌局可无限次,根据凯里公式最优的仓位比例是多少?

a. 10%

b. 20%

c. 40%

d. 60%

12、标普500的期望收益率是12%,无风险利率为5%,下面投资组合回报率最高的是哪个?

a. beta=0.2

b. beta=0.5

c. beta=1.1

d. beta=1.4

3. 公布答案

2017.03.19—07点公布答案!!

1-6: BDDCCB
7-12: BBCDBD

4. 获奖名单

请查看主办方的公众号,链接, 在微信里看。

注大家答题愉快!

写文章很辛苦,如果需要获得本文源代码或加入量化投资社群,请扫下面二维码,请作者喝杯咖啡。

转载请注明出处:
http://blog.fens.me/meeting-quant-20180315

打赏作者

用R语言解读凯利公式

用IT技术玩金融系列文章,将介绍如何使用IT技术,处理金融大数据。在互联网混迹多年,已经熟练掌握一些IT技术。单纯地在互联网做开发,总觉得使劲的方式不对。要想靠技术养活自己,就要把技术变现。通过“跨界”可以寻找新的机会,创造技术的壁垒。

金融是离钱最近的市场,也是变现的好渠道!今天就开始踏上“用IT技术玩金融”之旅!

关于作者:

  • 张丹(Conan), 程序员R,Nodejs,Java
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/finance-kelly

前言

职业做投机交易的人,应该都听说过凯利公式,这是一个通过计算胜率和赔率,来选择最佳投注比例的公式,目的是长期获得最高的盈利。

只要找到长期看必胜的局,接下来就是让时间帮我们赚钱了。

目录

  1. 开始赌局
  2. 凯利公式
  3. 赌局的最优解
  4. 让时间帮我们赚钱

1. 开始赌局

设游戏赌局,你赢的概率是80%,输的概率是20%,赢时的净收益率是100%,输时的亏损率也是100%。如果赢,你每赌1元可以赢得1元;如果输,则每赌1元将会输掉1元。赌局可以进行无限次,每次下的赌注可由你自己任意定。如果你的初始资金是100元,那么怎么样下注,才能使得长期收益最大?

对于胜率80%,从感觉上应该是很有把握的事情了。那么我们先主观判断一次,用90%的仓位去赌一下,看看结果怎么呢?如果下注10次,按80%胜率,8次胜,2次负。我们来算一下最后的结果。


# 设置胜负,1胜,0负
> win<-c(1,1,1,0,1,1,0,1,1,1)
 
# 分别按投注计算每回合的剩余资金 
> a1<-(1+0.9)*100
> a2<-a1*(1+0.9)
> a3<-a2*(1+0.9)
> a4<-a3*0.1
> a5<-a4*(1+0.9)
> a6<-a5*(1+0.9)
> a7<-a6*0.1
> a8<-a7*(1+0.9)
> a9<-a8*(1+0.9)
> a10<-a9*(1+0.9)
 
> dat<-c(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
> df<-data.frame(win,dat)

# 打印剩余资金列表
> df
   win      dat
1    1 190.0000
2    1 361.0000
3    1 685.9000
4    0  68.5900
5    1 130.3210
6    1 247.6099
7    0  24.7610
8    1  47.0459
9    1  89.3872
10   1 169.8356

10次交易后,赢了8次,只输了2次,我们从100元本金,上升到了169元,收益率为69%,还是不错的。最高的时候,资金为685元,收益率为685%,赚了6倍多。最低则是只剩下24元,真是赔的好惨啊!

接下来,画出资金曲线。这是一个过山车式的曲线,赚钱的时候非常猛,一旦赌输了,就产生了巨大的亏损。


# 画出资金曲线 
> plot(df$dat,type='l')

曲线很陡峭,波动很大,回撤也很大,完全就是在赌博。

怎么样才能让资金曲线好看一些呢?如果每次下注用少一点资金,是不是会更好呢?那么我继续试一下。分别计算每次下注资金为 60%,40%,20%,10%的4个维度的仓位的情况。


> library(magrittr)

# 定义现金流量函数:win=胜负结果,b=赔率,pos=仓位
> postion<-function(win,b=1,pos=0.6){            # 省略代码
+ }
 
# 设置胜负,1胜,0负
> win<-c(1,1,1,0,1,1,0,1,1,1) 
> prob<-0.8                      # 胜率
> n<-10                          # 赌局数
> b<-1                           # 赔率
> caption<-100                   # 金额
 
# 分别计算不同仓位的剩余现金
> pos90<-postion(win,b,0.9)*caption
> pos60<-postion(win,b,0.6)*caption
> pos40<-postion(win,b,0.4)*caption
> pos20<-postion(win,b,0.2)*caption
> pos10<-postion(win,b,0.1)*caption

# 合并到数据框
> df1<-data.frame(win,pos90,pos60,pos40,pos20,pos10)

# 打印计算结果
> df1
   win    pos90   pos60   pos40   pos20   pos10
1    1 190.0000 160.000 140.000 120.000 110.000
2    1 361.0000 256.000 196.000 144.000 121.000
3    1 685.9000 409.600 274.400 172.800 133.100
4    0  68.5900 163.840 164.640 138.240 119.790
5    1 130.3210 262.144 230.496 165.888 131.769
6    1 247.6099 419.430 322.694 199.066 144.946
7    0  24.7610 167.772 193.617 159.252 130.451
8    1  47.0459 268.435 271.063 191.103 143.496
9    1  89.3872 429.497 379.489 229.324 157.846
10   1 169.8356 687.195 531.284 275.188 173.631

我们看到,只是简单地调整了交易的仓位比例,那么交易10次后,你剩余的现是就是有很大的不同的。其中pos60列,即60%仓位的交易,获得的回报最高为687元,而90%的仓位获得的回报,是这里面最少的。而且非常有意思的是,后面的4种仓位设置,每次交易后的资金都大于100元的原始本金。

画出资金曲线


> library(ggplot2)
> library(scales)
> library(reshape2)

# 数据转型 
> df1$num<-1:nrow(df1)
> df<-melt(df1[,-1],id.vars="num")
 
# 画图 
> g<-ggplot(df,aes(x=num,y=value,colour=variable ))
> g<-g+geom_line()
> g

从图中可以看到,对于高胜率的情况,大的仓位是可以有高回报的,但是风险也大;小仓位是相对平稳的增长。

2. 凯利公式

那么多少的仓位是最优的呢?接下来的问题,就是凯利公式会告诉我们的。

在概率论中,凯利公式(The Kelly Criterion)是一个用以使特定赌局中,拥有正期望值之重复行为长期增长率最大化的公式,由约翰·拉里·凯利于1956年在《贝尔系统技术期刊》中发表,可用以计算出每次游戏中应投注的资金比例。

除可将长期增长率最大化外,此公式不会在任何赌局中,有失去全部现有资金的可能,因此有不存在破产疑虑的优点。公式中,假设货币与赌局可无限分割,只要资金足够多,长期一定是会赚到钱的。

凯利公式的最一般性陈述为,寻找能最大化结果对数期望值的资本比例f,即可获得长期增长率的最大化。对于只有两种结果的简单赌局而言,即 输失去所有本金,胜获得资金乘以特定的赔率。

可以用下面公式来表示:

其中

  • f* 投注的比例
  • b 赔率,盈亏比,即平均一次盈利与一次亏损两者的比例
  • p 胜率
  • q 败率,即 1 – p

用凯利公式对上面的例子进行测试,胜率p=0.8,失败率q=1-p=0.2,赔率b=1,失败则下注资金完全损失,计算下注比例为


f* = (b*p-q)/b = (1*0.8-0.2)/1=0.6

所以,赌客应在每次机会中下注现有资金的60%,可以获得最大化资金的长期增长率。

通过数学变型,可以很容易得到凯利公式的另一种表达式


Kelly % = W – [(1 – W) / R]

其中Kelly % 就是上式中的f*,W就是p胜率,R就是b赔率。两者看似不同,其实完全等效一致。

对于上面的例子,我们可以计算


Kelly % = W – [(1 – W) / R] = 0.8-[(1-0.8)/1] = 0.6 

凯利公式,有一个优化的变型。如果每次下注失败后,不是全部亏损,只是亏损部分,我们对上面公式可以做一个优化,增加亏损比例参数c,公式改写为下面格式


f* =  (b*p-c*q)/c*b

其中

  • f* 投注的比例
  • b 赔率,盈亏比,即平均一次盈利与一次亏损两者的比例
  • p 胜率
  • q 败率,即 1 – p
  • c 亏损比例

对于上面的例子,如果每次亏损是c=0.8,其他条件不变,那么我们应该用什么仓位进行交易呢?


f* = (b*p-q)/b = (1*0.8-0.8*0.2)/(0.8*1)=0.8

通过计算结果是0.8,我可以增大仓位。

凯利公式定义了长期获得最高的盈利的仓位确认的计算方法,我们自己也可以按照凯利公式的数学定义,进行推到一下。

假设一个赌局,每投资1,有p的概率可获得额外正收益W,有q=1-p的概率可获得额外的负收益-L,每次投资比例为x,建立收益为f(x)的目标函数,使得期望收益最大化。

转化为规划问题:

从推到可看出,标准的凯利公式只是当L=1的情况是一个应用,通过优化可增加了亏损比例参数。

3. 赌局的最优解

我们已经把公式介绍的很清楚了,那么接下来,就可以用程序实现进行实现了。


# 凯利公式,实现函数
> kelly<-function(prob,b=1,loss=1){   # 省略代码
+ }

用凯利公式计算的上文中的例子。


> prob<-0.8                     # 胜率
> b<-1                          # 赔率
> k<-kelly(prob,b,1);k
[1] 0.6

这时通过凯利公式,我们就能算出最最优的解其实是0.6的仓位设置,也就可以解释,上面的结果60%的仓位占比,获得的收益是最大的。

接下来,我们再比较一下不同的胜率和赔率的最优解是什么?

大胜率和大赔率时,可以重仓。当80%的胜率,2倍赔率时,仓位为70%。


> kelly(0.8,2)
[1] 0.7

通常情况下的赌局,不足50%的胜率,高赔率时,可以轻仓。当45%的胜率,2倍赔率时,仓位为17.5%。


> kelly(0.45,2)
[1] 0.175

通常情况下的赌局,不足50%的胜率,低赔率时,不要参考。当45%的胜率,1倍赔率时,不参与赌局。


> kelly(0.45,1)
[1] "Lost!!!"
[1] 0

小胜率,中等赔率时,不要参与。


> kelly(0.2,1)
[1] "Lost!!!"
[1] 0

小胜率,中等赔率时,中等损失,不要参与。


> kelly(0.2,1,0.5)
[1] "Lost!!!"
[1] 0

小胜率,中等赔率时,很小损失,可以All in。很小的损失比例,其实是变相的增大了赔率。


> kelly(0.2,1,0.1)
[1] "All In"
[1] 1

大胜率,很小赔率,很小损失,All in。


> kelly(0.8,0.1,0.1)
[1] "All In"
[1] 1

中胜率,很小赔率,很小损失,不要参与。


> kelly(0.45,0.1,0.1)
[1] "Lost!!!"
[1] 0

总结一下,投机操作的游戏规则。

胜率 赔率 损失率 仓位 指导建议 备注
80% 2 100% 70% 重仓 大胜率、大赔率、全部损失
45% 2 100% 17.5% 轻仓 中胜率、大赔率、全部损失
45% 1 100% 0 离场 中胜率、中赔率、全部损失
20% 1 100% 0 离场 小胜率、中赔率、全部损失
20% 1 50% 0 离场 小胜率、中赔率、中等损失
20% 1 10% 100% 满仓 小胜率、中赔率、小损失
80% 10% 10% 100% 满仓 大胜率、小赔率、小损失
45% 10% 10% 0 离场 中胜率、小赔率、小损失

这样我们就判断出,哪些投机操作值得玩,哪些不能玩,应该怎么玩。是不是很神奇!!

4. 让时间帮我们赚钱

根据凯利公式的定义,赌局可以进行无限次,那么当真的把赌局设置为很大时,会是什么情况呢?

我们把第一次的数据,进行100次的赌局,胜率为80%,赔率为1,金额100元,看一下结果。


> n<-100                          # 赌局数
> prob<-0.8                       # 胜率
> b<-1                            # 赔率
> caption<-100                    # 金额

# 基本二项分布,生成每盘的赌局正负
> set.seed(1)
> win<-rbinom(n,1,prob)
 
# 生成每盘的资金
> pos90<-postion(win,b,0.9)*caption   # 90%仓位
> pos60<-postion(win,b,0.6)*caption   # 60%仓位
> pos40<-postion(win,b,0.4)*caption   # 40%仓位
> pos20<-postion(win,b,0.2)*caption   # 20%仓位
> pos10<-postion(win,b,0.1)*caption   # 10%仓位

# 打印数据
> df2<-data.frame(win,pos90,pos60,pos40,pos20,pos10)
> tail(df2)
    win     pos90       pos60       pos40   pos20   pos10
95    1 105083487 5.73375e+11  9874948167 5067085 34506.6
96    1 199658625 9.17399e+11 13824927434 6080503 37957.3
97    1 379351388 1.46784e+12 19354898407 7296603 41753.0
98    1 720767637 2.34854e+12 27096857770 8755924 45928.3
99    0  72076764 9.39417e+11 16258114662 7004739 41335.5
100   1 136945851 1.50307e+12 22761360527 8405687 45469.0

从100盘赌局后的结果来看,60%的仓位可以获得最高收益的,为1.50307e+12,比其他的仓位都要高少非常。

接下来,我们生成资金曲线图。


# 数据转型
> df2$num<-1:nrow(df2)
> df<-melt(df2[,-1],id.vars = "num")

# 画图 
> g<-ggplot(df,aes(x=num,y=value,colour=variable ))
> g<-g+geom_line()
> g<-g+scale_y_log10()  # y坐标轴log化
> g

资金曲线图能非常直观地告诉了我们,什么的仓位有什么样曲线形状。你如果追求低风险,就用10%仓位稳健上涨。90%接近满仓并不是最赚钱的,反而是60%的仓位是有最大的回报。

我们再用凯利公式进行计算,可以发现结果最优的结果也是60%。


> kelly(prob,1)
[1] 0.6

神奇的算法,可以有效的帮我们控制仓位,最大化长期收益。只要找到长期必胜的局,接下来就是让时间帮我们赚钱了。下一篇文章,将介绍凯利公式在金融市场应用的应用。

写文章很辛苦,如果需要获得本文源代码或加入量化投资社群,请扫下面二维码,请作者喝杯咖啡。

转载请注明出处:
http://blog.fens.me/finance-kelly

打赏作者