0%

tomoon | 一个币种从选择到投入生产全过程

这里介绍了,量化系统中,从选取一个 coin 到正式跑量化的过程。

目前,程序跑的是 bsc 网络,只对接 pancakeswap

找 coin

coin 属性应该满足如下条件

  • 属于 bsc 网络的
  • cexdex 的名称
  • cexpair
  • cex 合约地址以及精度信息
    • 相关的合约地址,可以到下面的网址中查
    • coinmarketcap

ps: 2022-3-20

我将上述操作的全部合集代码放在了下面的博文中

查看 coin 在 cex 的情况

  • 一定要看提币手续费!!!
  • 一定要看提币手续费!!!
  • 一定要看提币手续费!!!

其中一个币的提币手续费竟然到了 60U 。千万不要懒!!!

查看 coin 是否满足条件

目前,量化只支持

swapExactTokensForTokens

所以,一旦链上信息存在 FeeOnTransferTokens 的函数,就要放弃了。

另外,即便是 swapExactTokensForTokens ,还需要查看这个 coin 是否燃烧等条件。

所有的信息,都要从链上获得,我总结了一些币种,可以查看

下面的脚本代码,可以检测该币种是否支持 swapExactTokensForTokens

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""
检测 swaptoken 是否可以
author: xiniu
"""
import time

from web3 import Web3

from config.contract import BSC_BUSD
from coin.coin import bsc

abi = """[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
"""
w3 = Web3(Web3.HTTPProvider("https://bsc-dataseed.binance.org/"))

contractObj = w3.eth.contract(
address=Web3.toChecksumAddress("0x10ed43c718714eb63d5aa57b78b54704e256024e"), abi=abi)

coins = ["CAKE"]
coin_pairs = ["WBNB"] # 最大池子的路径

contract_usdt = w3.eth.contract(
address=Web3.toChecksumAddress("0x55d398326f99059ff775485246999027b3197955"), abi=BSC_BUSD)


def get_usdt():
balance = contract_usdt.functions.balanceOf(dex_address).call()
return balance


def get_coin(contract, decimal_coin):
contract_coin = w3.eth.contract(
address=Web3.toChecksumAddress(contract), abi=BSC_BUSD)
balance = contract_coin.functions.balanceOf(dex_address).call()
return balance


def encode_swap(coin_amount, base_amount, paths, cex_address):
deadline = int(time.time()) + 300
tx_dic = contractObj.functions.swapExactTokensForTokens(
int(coin_amount),
int(base_amount - base_amount * 0.01),
paths,
# Web3.toChecksumAddress(cex_address),
Web3.toChecksumAddress(dex_address),
deadline
). \
buildTransaction(
{
'gas': 500000,
}
)
return tx_dic


def send_transaction(tx_dic):
nonce = w3.eth.getTransactionCount(dex_address)
print(nonce)
tx_dic["nonce"] = nonce
tx_dic['gasPrice'] = w3.eth.gasPrice
sign_tx = w3.eth.account.signTransaction(tx_dic, private_key=dex_private)
txn_hash = w3.eth.sendRawTransaction(sign_tx.rawTransaction)
return Web3.toHex(txn_hash)


def get_wait_receipt(tx):
data = w3.eth.waitForTransactionReceipt(tx)
return data


if __name__ == '__main__':
nonce = w3.eth.getTransactionCount(dex_address)
l = len(coins)
for i in range(l):
coin = coins[i]
print(coin)
coin_contract = bsc.get("coin").get(coin).get("address")
coin_pair = coin_pairs[i]
if coin_pair != "USDT":
dex_sell_paths = [Web3.toChecksumAddress(coin_contract),
Web3.toChecksumAddress(bsc.get("base").get(coin_pair)),
Web3.toChecksumAddress(bsc.get("base").get("USDT"))]
dex_buy_paths = [Web3.toChecksumAddress(bsc.get("base").get("USDT")),
Web3.toChecksumAddress(bsc.get("base").get(coin_pair)),
Web3.toChecksumAddress(coin_contract)]
else:
dex_sell_paths = [Web3.toChecksumAddress(coin_contract),
Web3.toChecksumAddress(bsc.get("base").get("USDT"))]
dex_buy_paths = [Web3.toChecksumAddress(bsc.get("base").get("USDT")), Web3.toChecksumAddress(coin_contract)]
usdt = get_usdt()
print(f"\t usdt: {usdt / (10 ** 18)}")
tx_dic = encode_swap(usdt, 0, dex_buy_paths, dex_address)
tx = send_transaction(tx_dic)
get_wait_receipt(tx)
while 1:
__nonce = w3.eth.getTransactionCount(dex_address)
if __nonce > nonce:
nonce = w3.eth.getTransactionCount(dex_address)
break
time.sleep(3)
coin_balance = get_coin(coin_contract, bsc.get("coin").get(coin).get("decimal"))
print(f'\t coin: {coin_balance / (10 ** bsc.get("coin").get(coin).get("decimal"))}')

tx_dic = encode_swap(coin_balance, 0, dex_sell_paths,
dex_address)
tx = send_transaction(tx_dic)
get_wait_receipt(tx)

while 1:
__nonce = w3.eth.getTransactionCount(dex_address)
if __nonce > nonce:
nonce = w3.eth.getTransactionCount(dex_address)
break
time.sleep(3)

usdt = get_usdt()
print(f"\t usdt: {usdt / (10 ** 18)}")

获得最大池子

因为,我们使用的是 swapExactTokensForTokens

所以,我目前的策略是,只在最大池子中交易。我试用了一个脚本来获得最大池子。

当知道最大池子后,我们就可以得到 paths

approval 授权

在正式跑量化的时候,我们还需要对钱包的这个 coin 进行授权,你可以参考我下面的博文。

请我喝杯咖啡吧~