BotVS数字货币现货交易类库
以下是BotVS数字货币现货交易类库模板,使用Python2语言实现
import types # 导入类型模块
import time # 导入时间模块
import platform # 版本信息
versionMainValue = None
isFirstCheck = True
# 判断数据类型
def typeOfstr(str):
if str == "list":
if versionMainValue == 2:
return types.ListType
elif versionMainValue == 3:
return list
elif str == "int":
if versionMainValue == 2:
return types.IntType
elif versionMainValue == 3:
return int
elif str == "float":
if versionMainValue == 2:
return types.FloatType
elif versionMainValue == 3:
return float
else:
Log("error , typeOfstr used false")
# 检测当前系统Python版本
def CheckVersion():
global versionMainValue,isFirstCheck
platformInfo = platform.python_version()
':
Log("您使用的托管者 python编译环境的python版本是",platformInfo)
versionMainValue = 2
':
Log("您使用的托管者 python编译环境的python版本是",platformInfo)
versionMainValue = 3
else:
Log("其它版本")
isFirstCheck = False
# 取消所有未完成挂单,orderType指定要买单还是卖单,或者都包括
def CancelPendingOrders(e, orderType = "") :
while True:
orders = e.GetOrders() #获取所有未成交的挂单
LogStatus("orders:",orders,time.time())
if(type(orders) != typeOfstr("list")): #异常处理: orders 类型不为list,表示获取数据出错。
Sleep(RetryDelay)
continue
processed = 0 # 计数器,统计有多少个挂单
for j in range(len(orders)): # 循环处理挂单,此处可以优化循环使用 for order in orders:
if (type(orderType) == typeOfstr("int") and orders[j].Type != orderType): #不是指定的订单类型不处理
continue
e.CancelOrder(orders[j].Id,orders[j]) #取消指定订单
processed += 1 #计数器加1
if (j < (len(orders) - 1)): #每处理一次,休息一下
Sleep(RetryDelay)
if(processed == 0):
break
# 获取账号信息 waitFrozen 是否等待冻结
def GetAccount(e, waitFrozen = False):
account = null
alreadyAlert = False #用于标记是否已提醒过
while True:
account = _C(e.GetAccount) #调用API 获取当前账户信息
if(not waitFrozen or (account.FrozenStocks < e.GetMinStock() and account.FrozenBalance < 0.01)):#不等待冻结或冻结数量小于最小交易量,直接中断循环
break
if(not alreadyAlert): #否则,并在没有提醒过时,则返回冻结信息
alreadyAlert = True
Log("发现账户有冻结的钱或币",account)
Sleep(RetryDelay) #[JS原注释]注意 : 如果有冻结的钱 或者 币 有可能一直卡在此处。
return account
# 取消 除参数指定的orderId 以外 的所有未成交的挂单。
def StripOrders(e,orderId = null):
order = null
while True:
dropped = 0 # 统计取消订单数
orders = _C(e.GetOrders) # 获取所有订单
for i in range(len(orders)):
if(orders[i].Id == orderId): #指定订单不处理
order = orders[i]
else: #其他订单都处理
extra = ""
if(orders[i].DealAmount > 0): #已经成交量
extra = "成交:" + str(orders[i].DealAmount)
else:
extra = "未成交"
e.CancelOrder(orders[i].Id, "买单" if orders[i].Type == ORDER_TYPE_BUY else "卖单",extra)
dropped += 1
if(dropped == 0):
break
Sleep(RetryDelay)
return order
# 交易函数,e:交易所对象, tradeType:交易类型 , tradeAmount:交易数量, mode:模式, slidePrice:滑价, maxAmount:单次最大交易量, maxSpace: 最大挂单距离, retryDelay: 重试时间。
# mode = 0 : direct buy吃单, 1 : buy as buy1 挂单
def Trade(e, tradeType, tradeAmount, mode, slidePrice, maxAmount, maxSpace, retryDelay):
initAccount = GetAccount(e,True) # 初始时 获取账户信息。
nowAccount = initAccount # 用于保存当前账户信息的变量,初始化为 initAccount
orderId = null # 声明一个用于保存 订单ID 的变量
prePrice = 0.0 # 上一次的价格
dealAmount = 0.0 # 已经处理过的(成交过的) 交易数量
diffMoney = 0.0 # 账户 钱之差
isFirst = True # 是否是 第一次的循环的 标记
tradeFunc = e.Buy if tradeType == ORDER_TYPE_BUY else e.Sell # 根据参数 tradeType 确定 调用API Buy 还是 Sell 。让 tradeFunc 引用相应的API接口。
isBuy = (tradeType == ORDER_TYPE_BUY) # 是否是 Buy的标记, 用 tradeFunc == ORDER_TYPEBUY 表达式的布尔值 初始化。
while True:
ticker = _C(e.GetTicker) # 获取当前行情数据 _C 重试函数
tradePrice = 0.0 # 初始交易价格 0
if(isBuy): # 如果是 买入操作
# 吃单或 挂单 价,再加滑价,来成交, (ticker.Buy + slidePrice) 为买一价+滑价,可能达不到卖1价,所以算挂单,但比挂1 高出一点,可能优先成交
tradePrice = _N((ticker.Sell if mode == 0 else ticker.Buy) + slidePrice,4)
else:
tradePrice = _N((ticker.Buy if mode == 0 else ticker.Sell) - slidePrice,4)
if(not orderId):
if(isFirst):
isFirst = False
else:
nowAccount = GetAccount(e,True)
doAmount = 0.0;
if(isBuy): # 如果是 买入操作
diffMoney = _N(initAccount.Balance - nowAccount.Balance,4) # 每次记录 ,用于最后计算 成交均价
dealAmount = _N(nowAccount.Stocks - initAccount.Stocks,4) # 实际已经 处理完成的量(成交)
doAmount = min(maxAmount,tradeAmount - dealAmount,_N((nowAccount.Balance - 10) / tradePrice,4)) # 根据几个待选 值取最小的。
else: # 处理 卖出的操作
diffMoney = _N(nowAccount.Balance - initAccount.Balance,4)
dealAmount = _N(initAccount.Stocks - nowAccount.Stocks,4)
doAmount = min(maxAmount,tradeAmount - dealAmount,nowAccount.Stocks)
if(doAmount < e.GetMinStock()): #要处理的量 小于 平台的最小成交量 ,即为交易完成,跳出循环
break
prePrice = tradePrice # 把本次循环计算出来的 交易价格 缓存到 prePrice 变量
orderId = tradeFunc(tradePrice, doAmount, ticker) # 下单 ,附带输出 ticker 数据
if(not orderId): # 如果 orderId 为 null ,取消所有挂单
CancelPendingOrders(e,tradeType)
else: # orderId 存在了
if(mode == 0 or (abs(tradePrice - prePrice) > maxSpace)): # 如果是挂单模式,超出挂单最大失效距离, 则把orderId赋值 为 null 。
orderId = null
order = StripOrders(e,orderId) # 取消 除orderId 以外的所有挂单,并返回 orderId 的 order信息
if(not order):
orderId = null
Sleep(retryDelay)
#处理量 小于等于 0 , 即 无法操作, 交易失败,返回 null
if(dealAmount <= 0):
Log("交易失败--TradeType:","buy" if tradeType == ORDER_TYPE_BUY else "sell"," ,diffMoney:",diffMoney," ,dealAmount",dealAmount," ,doAmount",doAmount)
return null
# 返回 成功的交易信息, 成交均价、 成交数量。
ret = {'price': _N(diffMoney/dealAmount,4),'amount':dealAmount}
return ret
# 导出函数 处理买入操作
def _Buy(e = exchange,amount = 0):
if isFirstCheck:
CheckVersion()
if (type(e) == typeOfstr("int") or type(e) == typeOfstr("float")):
amount = e
e = exchange
return Trade(e,ORDER_TYPE_BUY,amount,OpMode,SlidePrice,MaxAmount,MaxSpace,RetryDelay)
# 导出函数 处理卖出操作
def _Sell(e = exchange,amount = 0):
if isFirstCheck:
CheckVersion()
if (type(e) == typeOfstr("int") or type(e) == typeOfstr("float")):
amount = e
e = exchange
return Trade(e,ORDER_TYPE_SELL,amount,OpMode,SlidePrice,MaxAmount,MaxSpace,RetryDelay)
# 导出函数 用于 取消所有未完成 挂单
def _CancelPendingOrders(e = exchange,orderType = ""):
if isFirstCheck:
CheckVersion()
return CancelPendingOrders(e,orderType)
# 用于 获取当前账户信息 区别于 GetAccount(e, waitFrozen)
def _GetAccount(e = exchange):
if isFirstCheck:
CheckVersion()
return _C(e.GetAccount)
_MACalcMethod = [TA.EMA,TA.MA][MAType] #均线指标设置
Interval = 200
# 均线交叉 函数,用于 判断 均线交叉 返回上穿的周期数. 正数为上穿周数, 负数表示下穿的周数, 0指当前价格一样
def Cross(a,b):
if isFirstCheck:
CheckVersion()
crossNum = 0 # 交叉周期计数
arr1 = [] # 声明数组 arr1 用来 接收 指标数据 (数组结构)
arr2 = [] # 判断 参数 传入的是 周期数 还是 计算好的 指标数据(数组)
if type(a) == typeOfstr("list") and type(b) == typeOfstr("list"): # 如果是 数组 就把 a 参数(即指标数组)赋值给 arr1
arr1 = a
arr2 = b
else: # 如果传入的 a,b 不是 数组 ,是 周期数 执行一下。
records = null
while True:
records = exchange.GetRecords() # 调用 GetRecords 获取K线数据
if records and len(records) > a and len(records) > b: #判断 如果 records 获取到数据 并且 records K线数据 的 bar 个数(即 records 这个数组的长度) 大于 参数 周期数 a ,b ,代表符合计算指标的要求。(bar 个数不够 是计算不出指标数据的)
break
Sleep(Interval)
arr1 = _MACalcMethod(records,a) # 根据界面参数 MAType 的设置 引用 指标的函数名,在这里 传入K线数据,指标参数 周期数a , 去计算 指标数据,指标数据返回给 arr1
arr2 = _MACalcMethod(records,b) # MAType 是一个索引 ,根据 你界面上的设置 设置为相应的 索引 0 ~ n 自上而下, 这个索引 又确定了 [TA.EMA, TA.MA, talib.KAMA] 这个数组种 哪个 函数引用 赋值给 _MACalcMethod ,从而确定调用哪种 指标计算函数。
if len(arr1) != len(arr2): # 相同K线 计算出的 指标数据 长度 应当是一样的,不一样则异常
raise Exception("array length not equal")
for i in range(len(arr1) - 1,-1,-1): # 从指标数据 数组 自后向前 遍历数组
# 读取到任何 指标数据不为数值类型的时候就跳出,即 指标数据 由于计算周期不同,有数据 为null 了,无法比较 ,所以 只用 arr1 arr2 都是有效值的数据。
if (type(arr1[i]) != typeOfstr("int") and type(arr1[i]) != typeOfstr("float")) or (type(arr2[i]) != typeOfstr("int") and type(arr2[i]) != typeOfstr("float")):
break
# 此处 比较难以理解,由于crossNum 初始为0 , 不会触发一下 if 内的代码, arr1[i] 、arr2[i] 比较是 自后向前比较的, 即从离当前时间最近的 bar 的指标开始对比的, arr1[i] < arr2[i] 快线小于慢线,所以 在初始 crossNum 为0 的时候 ,快线小于慢线的 周期数 会持续记录在crossNum中, 直到 出现 arr1[i] > arr2[i] 的时候,此刻即 快线 慢线相交(这个时候break, crossNum 就是交叉后的周期数,最直观的就是 自己 模拟2组快慢线 数据数组,带入此处函数 根据逻辑 走一遍就明白了。)
if arr1[i] < arr2[i] :
if crossNum > 0 :
break
crossNum -= 1
elif arr1[i] > arr2[i] :
if crossNum < 0 :
break
crossNum += 1
else:
break
return crossNum
# 导出函数
ext.Buy = _Buy
ext.Sell = _Sell
ext.CancelPendingOrders = _CancelPendingOrders
ext.GetAccount = _GetAccount
ext.Cross = Cross
# 测试
def main():
ret = ext.Buy(0.2)
exchange.Sell(4500,1)
Sleep(10 * 1000)
ext.CancelPendingOrders()
Log("ret:",ret)
avgprice = ret['price']
dealamount = ret['amount']
Log("avgprice:",avgprice," dealamount:",dealamount)
模板参数

BotVS数字货币现货交易类库的更多相关文章
- 免费开源数字货币交易所——基于Java开发的比特币交易所 | BTC交易所 | ETH交易所 | 数字货币交易所
本项目是基于Java开发的比特币交易所 | BTC交易所 | ETH交易所 | 数字货币交易所 | 交易平台 | 撮合交易引擎.本项目基于SpringCloud微服务开发,可用来搭建和二次开发数字货币 ...
- 一步步教你创建自己的数字货币(代币)进行ICO
本文从技术角度详细介绍如何基于以太坊ERC20创建代币的流程. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以太坊是什么 ...
- ERC20数字货币ProxyOverflow存在漏洞
ERC20的ProxyOverflow漏洞造成影响广泛,本文将对其攻击方法进行分析,以便于智能合约发布者提高自身代码安全性以及其他研究人员进行测试.本文选择传播广泛.影响恶劣的SMT漏洞(CVE-20 ...
- 世界各国货币,C#数字货币计算
货币 CCY(Currency)本质上是一种所有者与市场关于交换权的契约,根本上是所有者相互之间的约定.吾以吾之所有予市场,换吾之所需,货币就是这一过程的约定,它反映的是个体与社会的经济协作关系.货币 ...
- 全球数字货币交易所TOP20安全性评级报告
链塔智库2018-05-03 10:28 分析师:常昊.王婧雯 来源: 链塔智库 全球加密数字货币市值超2.5万亿元,单日交易额超2000亿元,全球超过3000万人已投入加密数字货币领域. ...
- G20峰会将会给数字货币带来哪些影响?
G20峰会对于全球经济有着举足轻重的影响,其成员人口占全球的2/3,国土面积占全球的60%,国内生产总值占全球的90%,贸易额占全球的75%……作为国际经济合作的主要平台,G20在引领和推动国际经济合 ...
- 【课程笔记】比特币和数字货币技术[Bitcoin and Cryptocurrency Technologies] week1
源地址(可能要FQ):https://www.coursera.org/learn/cryptocurrency/home/welcome 1.1 Cryptographic Hash Functio ...
- PAY8 数字货币支付结算系统,全球付!实时结算!秒到账!
数字货币支付是历史发展的必然 如今已经有越来越多的地方接受加密数字货币作为支付消费了,比如泰国电影院连锁店 Cineplex Group 可用加密货币买爆米花和电影票,西班牙一精品酒店接受数字货币支付 ...
- [币严区块链]数字货币交易所之瑞波(XRP)钱包对接
对接Ripple(XRP),不需要本地部署钱包,直接访问Ripple API,本文包括访问Ripple API及如何免费获取测试的XRP. 对接流程 安装Ripple API Ripple API 接 ...
随机推荐
- 怎么调试nodejs restful API 以及API的Authorization
最近Nodejs,python越来越火了,同时也越来越多的人在用node写服务,可是怎么去调试服务呢?以及当你一个服务发布出去,怎么保证其安全性呢? 环境:linux unbuntu 语言:nodej ...
- CentOS7.2设置静态IP
首先将源文件进行备份: [zgw@localhost 桌面]$ sudo cp /etc/sysconfig/network-scripts/ifcfg-eno16777736 /etc/syscon ...
- hdu_1907:John(Nim变形)
题目链接 仍是取石子,不过取到最后一个的败 参考链接:http://www.voidcn.com/blog/liwen_7/article/p-3341825.html 简单一句话就是T2 S0必败 ...
- 51nod_1264:线段相交(计算几何)
题目链接 关于判断线段相交,具体算法见 点击打开链接 ,先进行快速排斥试验,若不能判断出两个线段不相交,再进行跨立试验. //吐槽1,long long 会溢出... //吐槽2,只进行跨立试验的虽然 ...
- 51nod_1119:机器人走方格 V2
题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1119 转化成杨辉三角就好辣@_@ #include< ...
- luoguP1886 滑动窗口 [单调队列]
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- Spring事件解析
首先介绍Spring事件相关类的关系: 其中EventListener与EventObject均是Java SE的范畴,源码如下: package java.util; public interfac ...
- Quartz.Net 与 Autofac 自动注入 的整合问题
一.问题发现 今天早上在用 Quartz.Net 做定时扫描异常队列的功能模块时,发现处理异常队列的Job里面的ILog对象服务,Autofac没有自动注入进来. 然后在网上查阅相关资料,无奈发现 Q ...
- css阴影,边框,渐变,背景
一.box-shadow: 参数1,参数2 阴影位置偏移量 参数3 模糊半径 参数4 扩展半径 负数 0 默认值 正数 参数5 阴影的颜色 参数6 设置内阴影 inset 默认是外阴影 多个阴影使用, ...
- 一步一步学Vue(九)
接上篇,这次是真的接上篇,针对上篇未完成的部分,增加鉴权功能,开始之前,我们先要介绍一个新的知识,路由元数据. 在vue-router中,定义元数据的方式: const router = new Vu ...