functionmain(){ var client =Dial("wss://stream.binance.com:9443/ws/!ticker@arr");while(true){ var data =client.read(); var msg =JSON.parse(data);updateTicker(msg);//updateTicker函数处理行情和交易,接下来介绍}}
var totalbtc = 0;//总价值,不一定是btc
var baseCoin = ['BTC', 'ETH', 'BNB', 'USDT'][baseCoin_select];//基础货币选择baseCoin_select是下拉框的一个参数
var exceptList = Except_list_string.split(',');//排除的币种,Except_list_string是策略参数
//K线周期选择PERIOD_M1,PERIOD_M5是FMZ默认的全局变量
var period = [PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H1, PERIOD_D1][period_select]
var periodSecond = [60, 300, 900, 1800, 3600, 3600*24][period_select]//各周期对应的秒数
var lastPeriodTime = 0;//最近周期时间,用于更新K线
var updateProfitTime = 0//最近更新收益时间,用于更新收益
var buyList = []//买单列表
var sellList = []//卖单列表
var accountInfo = {};//用于储存交易相关的数据列表
if (!_G('accountInfo')){//如果accountInfo没有储存在数据库里,重新获取数据
var exchangeInfo = JSON.parse(HttpQuery('https://api.binance.com/api/v1/exchangeInfo'));//获取交易相关数据
var ticker = JSON.parse(HttpQuery('https://api.binance.com/api/v1/ticker/24hr'));//先用rest协议获取一次全量ticekr
var tradeSymbol = exchangeInfo.symbols.filter(function(x){return x.quoteAsset == baseCoin});//筛选需要的交易对
accountInfo[baseCoin] = {free:0, frozen:0, last:1, value:0};//基础货币的信息
for (var i=0; i<tradeSymbol.length; i++){
var info = tradeSymbol[i];
if(exceptList.indexOf(info.symbol.slice(0,info.symbol.length-baseCoin.length)) >= 0){
continue;//过滤掉踢出的币种
}
for (var j=0; j<ticker.length; j++){
var symbol = info.symbol.slice(0,info.symbol.length-baseCoin.length)//币种名称
if(ticker[j].symbol.slice(ticker[j].symbol.length-baseCoin.length) == baseCoin && ticker[j].symbol == info.symbol){
//储存的exchangeInfo和ticker的内容,具体不过多解释
accountInfo[symbol] = {
last:parseFloat(ticker[j].lastPrice), free:0, frozen:0,
minQty:parseFloat(info.filters[2].minQty), minNotional:parseFloat(info.filters[3].minNotional)
tickerSize:parseFloat(info.filters[0].tickSize), stepSize:parseFloat(info.filters[2].stepSize),
ask:parseFloat(ticker[j].askPrice), bid:parseFloat(ticker[j].bidPrice), volume:parseFloat(ticker[j].quoteVolume),
lowPrice:parseFloat(ticker[j].lowPrice), highPrice:parseFloat(ticker[j].highPrice),
priceChangePercent:parseFloat(ticker[j].priceChangePercent),
sellPrice:0, buyPrice:0, state:0, value:0, records:null
}
break;
}
}
}
}else{
accountInfo = _G('accountInfo');
}
//退出时自动保存accountInfo到数据库
function onexit(){
_G('accountInfo', accountInfo);
}
function updateAccount(){
account = exchange.GetAccount();
if (!account){
Log('超时');
return;//这里直接返回是为了节约时间,账户信息获取不及时影响不大
}
for (var i=0; i<account.Info.balances.length; i++){
var symbol = account.Info.balances[i].asset
//都储存在accountInfo里
if (symbol in accountInfo){
accountInfo[symbol].free = parseFloat(account.Info.balances[i].free);
accountInfo[symbol].frozen = parseFloat(account.Info.balances[i].locked);
accountInfo[symbol].value = (accountInfo[symbol].free + accountInfo[symbol].frozen)*accountInfo[symbol].last
}
}
}
//更新当前账户总值,以所选的基础货币为单位
function updateTotalBTC(){
var btc = 0;
for (var symbol in accountInfo){
btc += accountInfo[symbol].value
totalbtc = btc;
}
}
function initRecords(){
for (var symbol in accountInfo){
if(symbol == baseCoin){continue}
if(!accountInfo[symbol].records){
var currency = symbol + '_' + baseCoin;
//切换交易对
exchange.IO("currency", currency)
accountInfo[symbol].records = exchange.GetRecords(period)
Log('更新', currency, 'K线', accountInfo[symbol].records[accountInfo[symbol].records.length-1])
Sleep(250)//每秒更新四个,不会达到限制
}
//最近K线时间
lastPeriodTime = Math.max(accountInfo[symbol].records[accountInfo[symbol].records.length-1].Time/1000, lastPeriodTime)
}
}
//根据推送ticker数据更新K线
function updateRecords(msgTime){
//如果当前时间大于最后更新的一个周期,说明需要产生新的K线
if(parseFloat(msgTime)/1000 - lastPeriodTime > periodSecond){
for (var symbol in accountInfo){
if(symbol != baseCoin){
//如果某交易对的K线差太多,就重新获取一次,可能是交易不活跃,ticker没推送
if(parseFloat(msgTime)/1000 - accountInfo[symbol].records[accountInfo[symbol].records.length-1].Time/1000 > 1.5*periodSecond){
var currency = symbol + '_' + baseCoin;
exchange.IO("currency", currency)
var records = exchange.GetRecords(period)
if(records){
accountInfo[symbol].records = exchange.GetRecords(period)
}
Log(symbol, 'K线有缺失,重新获取')
}else{
//推送一根新K线
accountInfo[symbol].records.push({"Time":parseInt(lastPeriodTime + periodSecond)*1000, "Open":accountInfo[symbol].last, "High":accountInfo[symbol].last,
"Low":accountInfo[symbol].last, "Close":accountInfo[symbol].last, "Volume":0})
}
}
}
lastPeriodTime = lastPeriodTime + periodSecond
Log(parseFloat(msgTime)/1000, '添加K线')
}else{
//如果在当前K线周期内,更新当前K线
for (var symbol in accountInfo){
if(symbol != baseCoin){
var length = accountInfo[symbol].records.length
accountInfo[symbol].records[length-1].Close = accountInfo[symbol].last
accountInfo[symbol].records[length-1].Volume += accountInfo[symbol].volume
if(accountInfo[symbol].last > accountInfo[symbol].records[length-1].High){
accountInfo[symbol].records[length-1].High = accountInfo[symbol].last
}
else if(accountInfo[symbol].last < accountInfo[symbol].records[length-1].Low){
accountInfo[symbol].records[length-1].Low = accountInfo[symbol].last
}
}
}
}
}
//取消当前交易对订单
function CancelPendingOrders() {
var orders = _C(exchange.GetOrders);
for (var j = 0; j < orders.length; j++) {
exchange.CancelOrder(orders[j].Id, orders[j]);
}
}
//取消所有交易对订单
function cancellAll(){
try{
var openOrders = exchange.IO('api', 'GET', '/api/v3/openOrders');
for (var i=0; i<openOrders.length; i++){
var order = openOrders[i];
var currency = order.symbol.slice(0,order.symbol.length-baseCoin.length) + '_' + baseCoin;
exchange.IO("currency", currency);
exchange.CancelOrder(order.orderId);
}
}
catch(err){
Log('取消订单失败');
}
for (var symbol in accountInfo){
accountInfo[symbol].state = 0;
accountInfo[symbol].buyprice = 0;
accountInfo[symbol].sellPrice = 0;
}
}
//下买单
function toBuy(){
//需要买的币种都储存在buyList种
if (buyList.length == 0){
return;
}
for (var i=0; i<buyList.length; i++){
var symbol = buyList[i];
//滑点是卖一价加最小交易单位,可能不会立即完全成交,可自行设置
var buyPrice = accountInfo[symbol].ask + accountInfo[symbol].tickerSize;
buyPrice = _N(buyPrice, parseInt((Math.log10(1.1/accountInfo[symbol].tickerSize))));//满足价格精度
var currency = symbol + '_' + baseCoin;
exchange.IO("currency", currency);//切换交易对
//如果已经下单,并和本次价格相同,不操作
if (accountInfo[symbol].state && accountInfo[symbol].bid == accountInfo[symbol].buyprice){
continue;
}else{
//已下单先撤销
if (accountInfo[symbol].state == 1){
CancelPendingOrders();
accountInfo[symbol].state = 0;
accountInfo[symbol].buyprice = 0;
}
var amount = (accountInfo[symbol].free + accountInfo[symbol].frozen)*buyPrice; //现有币种的价值
var needBuyBTC = HoldAmount - amount;/HoldAmount是全局参数,需要持有的价值
var buyAmount = needBuyBTC/buyPrice;
buyAmount = _N(scale*buyAmount, parseInt((Math.log10(1.1/accountInfo[symbol].stepSize))));//下单量精度
//满足最小交易量和最小交易价值要求
if (buyAmount > accountInfo[symbol].minQty && buyPrice*buyAmount > accountInfo[symbol].minNotional){
if (accountInfo[baseCoin].free < buyPrice*buyAmount){return;}//有足够的基础货币购买
var id = exchange.Buy(buyPrice, buyAmount, currency);//最终下单
if(id){
accountInfo[symbol].buyprice = buyPrice;
accountInfo[symbol].state = 1;
}
}
}
//如果买单过多,需要休眠,币安1s最多下10单
if(buyList.length > 5){
Sleep(200)
}
}
}
//下卖单原理与买单相似
function toSell(){
if (sellList.length == 0){
return;
}
for (var i=0; i<sellList.length; i++){
var currency = symbol + '_' + baseCoin;
exchange.IO("currency", currency);
var sellPrice = accountInfo[symbol].bid - accountInfo[symbol].tickerSize;
sellPrice = _N(sellPrice, parseInt((Math.log10(1.1/accountInfo[symbol].tickerSize))));
if (accountInfo[symbol].state == 1 && accountInfo[symbol].bid != accountInfo[symbol].buyprice){
CancelPendingOrders();
accountInfo[symbol].state = 0;
accountInfo[symbol].sellPrice = 0;
}
var sellAmount = accountInfo[symbol].free;
sellAmount = _N(Math.min(scale*sellAmount,accountInfo[symbol].free), parseInt((Math.log10(1.1/accountInfo[symbol].stepSize))));
if (sellAmount > accountInfo[symbol].minQty && sellPrice*sellAmount > accountInfo[symbol].minNotional){
var id = exchange.Sell(sellPrice, sellAmount, currency);
if(id){
accountInfo[symbol].state = 1;
accountInfo[symbol].sellPrice = sellPrice;
}
}
if(sellList.length > 5){
Sleep(200)
}
}
}
function checkTrade(){
buyList = []
sellList = []
for(var symbol in accountInfo){
if(symbol == baseCoin){
continue
}
var length = accountInfo[symbol].records.length
//简单均线,只做一个简单的演示例子,不要实盘使用,自己交易咯及放在这里就可以了
var fast = TA.MA(accountInfo[symbol].records, FastPeriod)[length-1]
var slow = TA.MA(accountInfo[symbol].records, SlowPeriod)[length-1]
if(accountInfo[symbol].value > 2*accountInfo[symbol].minNotional && fast < 0.99*slow){
sellList.push(symbol)
}
//HoldAmount策略参数
if(accountInfo[symbol].value < 0.9*HoldAmount && fast > 1.01*slow){
buyList.push(symbol)
}
}
}
function main() {
cancellAll();
initRecords()
updateAccount();
updateTotalBTC()
Log('共交易数字货币:', Object.keys(accountInfo).length-1);
updateStatus();
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
while (true){
var data = client.read();
var msg = JSON.parse(data);
updateTicker(msg);
}
}