void main() {
Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body");
}
Mail
Versão assíncrona da funçãoMail_Go
Função:
Utilização eexchange.Go
A função é semelhante.
function main() {
var r1 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
var r2 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
var ret1 = r1.wait()
var ret2 = r2.wait()
Log("ret1:", ret1)
Log("ret2:", ret2)
}
# 不支持
// 不支持
Atenção:
O servidor da Ali Cloud pode bloquear algumas portas, o que faz com que o e-mail não possa ser enviado. Se você precisar mudar a porta, pode adicionar diretamente o número do porto no primeiro parâmetro, por exemplo:smtp.qq.com:587
O teste de porta está disponível.
Se houver um erro:unencryped connection
O que é necessário?Mail
FunçõessmtpServer
O formato dos parâmetros é:ssl://xxx.com:xxx
Por exemplo, no QQ.SMTP
O método de SSL:ssl://smtp.qq.com:465
Ousmtp://xxx.com:xxx
。
SetErrorFilter(RegEx)
, filtragem de logs de erros↑ valor de parâmetro: tipo de string↑
Os registros de erros correspondentes a esta expressão regular não serão carregados para o sistema de registros, podendo ser chamados várias vezes para definir várias condições de filtragem (os registros filtrados não são escritos em arquivos de banco de dados que correspondem ao ID de disco real no diretório do administrador, evitando que erros frequentes causem o excesso de arquivos de banco de dados).
function main() {
SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
}
def main():
SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
void main() {
SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused");
}
Filtrar uma mensagem de erro de interface:
function main() {
// 随便查询一个不存在的订单,id为123,故意让接口报错
var order = exchange.GetOrder("123")
Log(order)
// 过滤http502错误、GetOrder接口错误,设置错误过滤之后,第二次调用GetOrder不再报错
SetErrorFilter("502:|GetOrder")
order = exchange.GetOrder("123")
Log(order)
}
def main():
order = exchange.GetOrder("123")
Log(order)
SetErrorFilter("502:|GetOrder")
order = exchange.GetOrder("123")
Log(order)
void main() {
TId orderId;
Order order = exchange.GetOrder(orderId);
Log(order);
SetErrorFilter("502:|GetOrder");
order = exchange.GetOrder(orderId);
Log(order);
}
GetPid()
, retorna o ID do processo de disco real.
function main(){
var id = GetPid()
Log(id)
}
def main():
id = GetPid()
Log(id)
void main() {
auto id = GetPid();
Log(id);
}
GetLastError()
, para obter informações de erro mais recentes. Geralmente não é necessário, pois o programa envia automaticamente informações de erro para o sistema de logs. Retorna o valor: tipo de string.GetLastError()
A função limpa o cache de erro e não retorna a mensagem de erro da última gravação quando for chamada novamente.
function main(){
// 因为不存在编号为123的订单,所以会出错
exchange.GetOrder("123")
var error = GetLastError()
Log(error)
}
def main():
exchange.GetOrder("123")
error = GetLastError()
Log(error)
void main() {
// 订单ID类型:TId,所以不能传入字符串,我们下一个不符合交易所规范的订单来触发
exchange.GetOrder(exchange.Buy(1, 1));
auto error = GetLastError();
Log(error);
}
GetCommand()
, obtém a sequência de comandos interativos ((utf-8)); obtém o comando enviado pela interface de interação da política e limpa o cache, não há comando e retorna a sequência de comandos em branco. O formato do comando de retorno é按钮名称:参数
Se o controle interativo não tiver parâmetros (por exemplo, um controle de botão sem caixa de entrada), o comando é o nome do botão.
function main(){
while(true) {
var cmd = GetCommand()
if (cmd) {
Log(cmd)
}
Sleep(1000)
}
}
def main():
while True:
cmd = GetCommand()
if cmd:
Log(cmd)
Sleep(1000)
void main() {
while(true) {
auto cmd = GetCommand();
if(cmd != "") {
Log(cmd);
}
Sleep(1000);
}
}
O sistema subjacente tem uma estrutura de fila para registrar as instruções de interação quandoGetCommand()
Quando a função é chamada, ela retira o comando de interação que entrou primeiro na fila (e retorna uma string vazia se não houver um comando de interação).
Exemplos de uso de controles interativos, interface de edição de estratégias para configurar controles interativos.
A estratégia é projetar código interativo:
function main() {
while (true) {
LogStatus(_D())
var cmd = GetCommand()
if (cmd) {
Log("cmd:", cmd)
var arr = cmd.split(":")
if (arr[0] == "buy") {
Log("买入,该控件不带数量")
} else if (arr[0] == "sell") {
Log("卖出,该控件带数量:", arr[1])
} else {
Log("其它控件触发:", arr)
}
}
Sleep(1000)
}
}
def main():
while True:
LogStatus(_D())
cmd = GetCommand()
if cmd:
Log("cmd:", cmd)
arr = cmd.split(":")
if arr[0] == "buy":
Log("买入,该控件不带数量")
elif arr[0] == "sell":
Log("卖出,该控件带数量:", arr[1])
else:
Log("其它控件触发:", arr)
Sleep(1000)
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
void split(const string& s,vector<string>& sv,const char flag = ' ') {
sv.clear();
istringstream iss(s);
string temp;
while (getline(iss, temp, flag)) {
sv.push_back(temp);
}
return;
}
void main() {
while(true) {
LogStatus(_D());
auto cmd = GetCommand();
if (cmd != "") {
vector<string> arr;
split(cmd, arr, ':');
if(arr[0] == "buy") {
Log("买入,该控件不带数量");
} else if (arr[0] == "sell") {
Log("卖出,该控件带数量:", arr[1]);
} else {
Log("其它控件触发:", arr);
}
}
Sleep(1000);
}
}
GetMeta()
A função retorna o código de registo da política de geração.Meta
O valor que a função retorna é o tipo de string.
Cenários de aplicação, como a estratégia de limitar o financiamento de diferentes inquilinos.
Nota: O código de registo é geradoMeta
A função não pode exceder 190 caracteres de comprimento e é aplicada somente ao disco físico e requer o uso do administrador mais recente.GetMeta()
Retorna um valor em branco.
Informações sobre demonstrações de cenários
function main() {
// 策略允许的计价币最大资产数值
var maxBaseCurrency = null
// 获取创建注册码时的元数据
var level = GetMeta()
// 检测Meta对应的条件
if (level == "level1") {
// -1为不限制
maxBaseCurrency = -1
} else if (level == "level2") {
maxBaseCurrency = 10
} else if (level == "level3") {
maxBaseCurrency = 1
} else {
maxBaseCurrency = 0.5
}
while(1) {
Sleep(1000)
var ticker = exchange.GetTicker()
// 检测资产数值
var acc = exchange.GetAccount()
if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
// 停止执行策略交易逻辑
LogStatus(_D(), "level:", level, "持仓超过注册码的使用限定,不再执行策略交易逻辑!")
continue
}
// 其它交易逻辑
// 正常输出状态栏信息
LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\n", ticker)
}
}
def main():
maxBaseCurrency = null
level = GetMeta()
if level == "level1":
maxBaseCurrency = -1
elif level == "level2":
maxBaseCurrency = 10
elif level == "level3":
maxBaseCurrency = 1
else:
maxBaseCurrency = 0.5
while True:
Sleep(1000)
ticker = exchange.GetTicker()
acc = exchange.GetAccount()
if maxBaseCurrency != -1 and maxBaseCurrency < acc["Stocks"] + acc["FrozenStocks"]:
LogStatus(_D(), "level:", level, "持仓超过注册码的使用限定,不再执行策略交易逻辑!")
continue
# 其它交易逻辑
# 正常输出状态栏信息
LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\n", ticker)
void main() {
auto maxBaseCurrency = 0.0;
auto level = GetMeta();
if (level == "level1") {
maxBaseCurrency = -1;
} else if (level == "level2") {
maxBaseCurrency = 10;
} else if (level == "level3") {
maxBaseCurrency = 1;
} else {
maxBaseCurrency = 0.5;
}
while(1) {
Sleep(1000);
auto ticker = exchange.GetTicker();
auto acc = exchange.GetAccount();
if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
// 停止执行策略交易逻辑
LogStatus(_D(), "level:", level, "持仓超过注册码的使用限定,不再执行策略交易逻辑!");
continue;
}
// 其它交易逻辑
// 正常输出状态栏信息
LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\n", ticker);
}
}
Dial(Address, Timeout)
O que é isso?Socket
Acesso, apoiotcp
,udp
,tls
,unix
Protocolo. Parâmetro:Address
Para o tipo de strings,TimeOut
Para o tipo de valor, a unidade de valor é o segundo, se ultrapassar o tempoDial(...)
A função retorna um valor em branco.
Address
Os parâmetros são detalhados:
– | Parâmetros |
---|---|
ConfiguraçãoDial Parâmetros da função |
O endereço normal é:wss://ws.okx.com:8443/ws/v5/public Mais tarde| Separador de símbolos, se houver uma string de parâmetros| Os caracteres são:|| Como símbolo de separação.& Conexão de caracteres. Por exemplo, os agentes ss5 e os parâmetros de compressão são definidos juntos:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv") 。 |
Quando usado no protocolo ws, os parâmetros relacionados à compressão de dados são:compress=参数值 |
compress como modo de compressão, parâmetros de compressão, opcionalgzip_raw 、gzip Por exemplo. Se o gzip não for o padrão, pode ser usado como uma extensão:gzip_raw O que é um ponto de separação| Adicionar configurações depoiscompress=gzip_raw , com& O símbolo e o parâmetro de modo seguinte são separados. |
Quando usado no protocolo ws, os parâmetros relacionados à compressão de dados são:mode=参数值 |
modo para o modo, opcionaldual ,send ,recv Três.dual Para ambos os lados, enviar dados de compressão e receber dados de compressão.send Para enviar dados de compressão.recv Para receber os dados de compressão, decomprime localmente. |
Os parâmetros relevantes para a configuração do agente socks5 são:proxy=参数值 |
O proxy é configurado para ser um agente ss5, com o formato de parâmetros:socks5://name:pwd@192.168.0.1:1080 O nome é o nome de usuário do servidor ss5, o pwd é o código de acesso ao servidor ss5 e o porto 1080 é o servidor ss5. |
Quando usado no protocolo ws, configure os parâmetros relacionados ao reencadeamento automático no nível inferior:reconnect=参数值 |
O reconnect é para saber se a rede é definida.reconnect=true Para habilitar a recombinação. Não recombinar por defeito sem este parâmetro. |
Quando usado no protocolo ws, configure os parâmetros relacionados ao reencadeamento automático no nível inferior:interval=参数值 |
Intervalo é o intervalo de tempo de reexame, em milissegundos.interval=10000 Para tentar de novo com um intervalo de 10 segundos, não defina 1 segundo, ou seja,interval=1000 。 |
Quando usado no protocolo ws, configure os parâmetros relacionados ao reencadeamento automático no nível inferior:payload=参数值 |
mensagens de subscrição que devem ser enviadas quando o payload é religado para ws, por exemplo:payload=okok 。 |
function main(){
// Dial支持tcp://,udp://,tls://,unix://协议,可加一个参数指定超时的秒数
var client = Dial("tls://www.baidu.com:443")
if (client) {
// write可再跟一个数字参数指定超时,write返回成功发送的字节数
client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
while (true) {
// read可再跟一个数字参数指定超时,单位:毫秒。返回null指出错或者超时或者socket已经关闭
var buf = client.read()
if (!buf) {
break
}
Log(buf)
}
client.close()
}
}
def main():
client = Dial("tls://www.baidu.com:443")
if client:
client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
while True:
buf = client.read()
if not buf:
break
Log(buf)
client.close()
void main() {
auto client = Dial("tls://www.baidu.com:443");
if(client.Valid) {
client.write("GET / HTTP/1.1\nConnection: Closed\n\n");
while(true) {
auto buf = client.read();
if(buf == "") {
break;
}
Log(buf);
}
client.close();
}
}
read
A função suporta os seguintes parâmetros:
ws.read()
。ws.read(2000)
O tempo de atraso especificado é de dois segundos (~2000 milissegundos).websocket
Eficaz:
Parâmetros de entrada-1
A função retorna imediatamente, independentemente da existência de uma mensagem, por exemplo:ws.read(-1)
Não, não é.
Parâmetros de entrada-2
Isso significa que a função retorna imediatamente, independentemente de não haver mensagens, mas só retorna as mensagens mais recentes, e as mensagens do buffer são descartadas; por exemplo:ws.read(-2)
。read()
A área de buffer da função explica:
Os dados enviados pelo protocolo ws, se estiverem na políticaread()
O intervalo de tempo entre as chamadas de funções pode ser muito longo, o que pode causar acumulação de dados. Estes dados são armazenados em buffers, com uma estrutura de dados de buffers de filas, com um limite máximo de 2.000. Após 2000, os dados mais recentes entram em buffers e os mais antigos são eliminados.
A cena.read Parâmetros de função |
Sem parâmetros | Parâmetros: -1 | Parâmetros: -2 | Parâmetros: 2000 unidades são milissegundos |
---|---|---|---|---|
Os dados já estão disponíveis. | Retorno imediato aos dados mais antigos | Retorno imediato aos dados mais antigos | Volte imediatamente para os dados atualizados | Retorno imediato aos dados mais antigos |
Não há dados na zona de reserva | Bloquear até que haja dados | Retorna um valor em branco imediatamente. | Retorna um valor em branco imediatamente. | Espere 2000 milissegundos, nenhum dado retornará um valor em branco, mas alguns dados retornarão |
Ws quando a conexão é cortada ou quando o fundo é religado | A função read (()) retorna uma cadeia de caracteres em branco, como: "", write (()) retorna 0, e detecta essa situação. A função close (()) pode ser usada para fechar a conexão, mas não precisa ser fechada se for definida a reconexão automática. |
Suporte ao protocolo wss (WebSocket) Para acessar o interface do mercado do websocket da Binance:
function main() {
LogStatus("正在连接...")
// 访问币安的websocket接口
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
if (!client) {
Log("连接失败, 程序退出")
return
}
while (true) {
// read只返回调用read之后获取的数据
var buf = client.read()
if (!buf) {
break
}
var table = {
type: 'table',
title: '行情图表',
cols: ['币种', '最高', '最低', '买一', '卖一', '最后成交价', '成交量', '更新时间'],
rows: []
}
var obj = JSON.parse(buf)
_.each(obj, function(ticker) {
table.rows.push([ticker.s, ticker.h, ticker.l, ticker.b, ticker.a, ticker.c, ticker.q, _D(ticker.E)])
})
LogStatus('`' + JSON.stringify(table) + '`')
}
client.close()
}
import json
def main():
LogStatus("正在连接...")
client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
if not client:
Log("连接失败, 程序退出")
return
while True:
buf = client.read()
if not buf:
break
table = {
"type" : "table",
"title" : "行情图表",
"cols" : ["币种", "最高", "最低", "买一", "卖一", "最后成交价", "成交量", "更新时间"],
"rows" : []
}
obj = json.loads(buf)
for i in range(len(obj)):
table["rows"].append([obj[i]["s"], obj[i]["h"], obj[i]["l"], obj[i]["b"], obj[i]["a"], obj[i]["c"], obj[i]["q"], _D(int(obj[i]["E"]))])
LogStatus('`' + json.dumps(table) + '`')
client.close()
void main() {
LogStatus("正在连接...");
auto client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
if(!client.Valid) {
Log("连接失败, 程序退出");
return;
}
while(true) {
auto buf = client.read();
if(buf == "") {
break;
}
json table = R"({
"type" : "table",
"title" : "行情图表",
"cols" : ["币种", "最高", "最低", "买一", "卖一", "最后成交价", "成交量", "更新时间"],
"rows" : []
})"_json;
json obj = json::parse(buf);
for(auto& ele : obj.items()) {
table["rows"].push_back({ele.value()["s"], ele.value()["h"], ele.value()["l"], ele.value()["b"], ele.value()["a"], ele.value()["c"],
ele.value()["q"], _D(ele.value()["E"])});
}
LogStatus("`" + table.dump() + "`");
}
client.close();
}
Para acessar a interface de mercado do websocket do OKX:
var ws = null
function main(){
var param = {
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
}
// 在调用Dial函数时,指定reconnect=true即设置为重连模式,指定payload即为重连时发送的消息。在websocket连接断开后,会自动重连,自动发送消息
ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
if(ws){
var pingCyc = 1000 * 20
var lastPingTime = new Date().getTime()
while(true){
var nowTime = new Date().getTime()
var ret = ws.read()
Log("ret:", ret)
if(nowTime - lastPingTime > pingCyc){
var retPing = ws.write("ping")
lastPingTime = nowTime
Log("发送 :ping", "#FF0000")
}
LogStatus("当前时间:", _D())
Sleep(1000)
}
}
}
function onexit() {
ws.close()
Log("退出")
}
import json
import time
ws = None
def main():
global ws
param = {
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
}
ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload=" + json.dumps(param))
if ws:
pingCyc = 1000 * 20
lastPingTime = time.time() * 1000
while True:
nowTime = time.time() * 1000
ret = ws.read()
Log("ret:", ret)
if nowTime - lastPingTime > pingCyc:
retPing = ws.write("ping")
lastPingTime = nowTime
Log("发送:ping", "#FF0000")
LogStatus("当前时间:", _D())
Sleep(1000)
def onexit():
ws.close()
Log("退出")
auto objWS = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true");
void main() {
json param = R"({
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
})"_json;
objWS.write(param.dump());
if(objWS.Valid) {
uint64_t pingCyc = 1000 * 20;
uint64_t lastPingTime = Unix() * 1000;
while(true) {
uint64_t nowTime = Unix() * 1000;
auto ret = objWS.read();
Log("ret:", ret);
if(nowTime - lastPingTime > pingCyc) {
auto retPing = objWS.write("ping");
lastPingTime = nowTime;
Log("发送:ping", "#FF0000");
}
LogStatus("当前时间:", _D());
Sleep(1000);
}
}
}
void onexit() {
objWS.close();
Log("退出");
}
A interface de mercado do websocket para acessar os tokens:
var ws = null
function main(){
var param = {"sub": "market.btcusdt.detail", "id": "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
if(ws){
while(1){
var ret = ws.read()
Log("ret:", ret)
// 响应心跳包操作
try {
var jsonRet = JSON.parse(ret)
if(typeof(jsonRet.ping) == "number") {
var strPong = JSON.stringify({"pong" : jsonRet.ping})
ws.write(strPong)
Log("响应ping,发送pong:", strPong, "#FF0000")
}
} catch(e) {
Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
}
LogStatus("当前时间:", _D())
Sleep(1000)
}
}
}
function onexit() {
ws.close()
Log("执行ws.close()函数")
}
import json
ws = None
def main():
global ws
param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
if ws:
while True:
ret = ws.read()
Log("ret:", ret)
# 响应心跳包操作
try:
jsonRet = json.loads(ret)
if "ping" in jsonRet and type(jsonRet["ping"]) == int:
strPong = json.dumps({"pong" : jsonRet["ping"]})
ws.write(strPong)
Log("响应ping,发送pong:", strPong, "#FF0000")
except Exception as e:
Log("e:", e)
LogStatus("当前时间:", _D())
Sleep(1000)
def onexit():
ws.close()
Log("执行ws.close()函数")
using namespace std;
void main() {
json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
if(ws.Valid) {
while(true) {
auto ret = ws.read();
Log("ret:", ret);
// 响应心跳包操作
try
{
auto jsonRet = json::parse(ret);
if(jsonRet["ping"].is_number()) {
json pong = R"({"pong" : 0})"_json;
pong["pong"] = jsonRet["ping"];
auto strPong = pong.dump();
ws.write(strPong);
Log("响应ping,发送pong:", strPong, "#FF0000");
}
} catch(exception &e)
{
Log("e:", e.what());
}
LogStatus("当前时间:", _D());
Sleep(1000);
}
}
}
void onexit() {
// ws.close();
Log("执行ws.close()函数");
}
Para acessar a interface de verificação do websocket do OKX:
function getLogin(pAccessKey, pSecretKey, pPassphrase) {
// 签名函数,用于登录
var ts = (new Date().getTime() / 1000).toString()
var login = {
"op": "login",
"args":[{
"apiKey" : pAccessKey,
"passphrase" : pPassphrase,
"timestamp" : ts,
"sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
}]
}
return login
}
var client_private = null
function main() {
// 因为read函数使用了超时设置,过滤超时的报错,否则会有冗余错误输出
SetErrorFilter("timeout")
// 持仓频道订阅信息
var posSubscribe = {
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
}
var accessKey = "xxx"
var secretKey = "xxx"
var passphrase = "xxx"
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000) // 登录时,不能立即订阅私有频道,需要等待服务器反应
client_private.write(JSON.stringify(posSubscribe))
if (client_private) {
var lastPingTS = new Date().getTime()
while (true) {
var buf = client_private.read(-1)
if (buf) {
Log(buf)
}
// 检测断开,重连
if (buf == "" && client_private.write(JSON.stringify(posSubscribe)) == 0) {
Log("检测到断开,关闭连接,重连")
client_private.close()
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(JSON.stringify(posSubscribe))
}
// 发送心跳包
var nowPingTS = new Date().getTime()
if (nowPingTS - lastPingTS > 10 * 1000) {
client_private.write("ping")
lastPingTS = nowPingTS
}
}
}
}
function onexit() {
var ret = client_private.close()
Log("关闭连接!", ret)
}
import json
import time
def getLogin(pAccessKey, pSecretKey, pPassphrase):
ts = str(time.time())
login = {
"op": "login",
"args":[{
"apiKey" : pAccessKey,
"passphrase" : pPassphrase,
"timestamp" : ts,
"sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
}]
}
return login
client_private = None
def main():
global client_private
SetErrorFilter("timeout")
posSubscribe = {
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
}
accessKey = "xxx"
secretKey = "xxx"
passphrase = "xxx"
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(json.dumps(posSubscribe))
if client_private:
lastPingTS = time.time() * 1000
while True:
buf = client_private.read(-1)
if buf:
Log(buf)
if buf == "" and client_private.write(json.dumps(posSubscribe)) == 0:
Log("检测到断开,关闭连接,重连")
ret = client_private.close()
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(json.dumps(posSubscribe))
nowPingTS = time.time() * 1000
if nowPingTS - lastPingTS > 10 * 1000:
client_private.write("ping")
lastPingTS = nowPingTS
def onexit():
ret = client_private.close()
Log("关闭连接!", ret)
auto client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
json getLogin(string pAccessKey, string pSecretKey, string pPassphrase) {
auto ts = std::to_string(Unix());
json login = R"({
"op": "login",
"args": [{
"apiKey": "",
"passphrase": "",
"timestamp": "",
"sign": ""
}]
})"_json;
login["args"][0]["apiKey"] = pAccessKey;
login["args"][0]["passphrase"] = pPassphrase;
login["args"][0]["timestamp"] = ts;
login["args"][0]["sign"] = exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey);
return login;
}
void main() {
SetErrorFilter("timeout");
json posSubscribe = R"({
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
})"_json;
auto accessKey = "xxx";
auto secretKey = "xxx";
auto passphrase = "xxx";
client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
Sleep(3000);
client_private.write(posSubscribe.dump());
if (client_private.Valid) {
uint64_t lastPingTS = Unix() * 1000;
while (true) {
auto buf = client_private.read(-1);
if (buf != "") {
Log(buf);
}
if (buf == "") {
if (client_private.write(posSubscribe.dump()) == 0) {
Log("检测到断开,关闭连接,重连");
client_private.close();
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
Sleep(3000);
client_private.write(posSubscribe.dump());
}
}
uint64_t nowPingTS = Unix() * 1000;
if (nowPingTS - lastPingTS > 10 * 1000) {
client_private.write("ping");
lastPingTS = nowPingTS;
}
}
}
}
void onexit() {
client_private.close();
Log("退出");
}
HttpQuery(Url, PostData, Cookies, Headers, IsReturnHeader)
, acesso a URLs de rede.
Atenção:
HttpQuery(...)
Funções apenas suportadasJavaScript
A língua.Python
A linguagem pode ser usadaurllib
O Google pode enviar uma solicitação http diretamente.HttpQuery(...)
A maioria das vezes, é usado para acessar interfaces que não requerem assinatura, como as interfaces públicas, como informações de mercado.
Exemplo de interface API que não requer assinatura para acessar o OKX e retorna o valorJSON
O que você está fazendo?JavaScript
A estratégia da linguagem pode ser usadaJSON.parse()
Função de análise.
function main(){
// 一个GET访问不带参数的例子
var info = JSON.parse(HttpQuery("https://www.okx.com/api/v5/public/time"))
Log(info)
// 一个GET访问带参数的例子
var ticker = JSON.parse(HttpQuery("https://www.okx.com/api/v5/market/books?instId=BTC-USDT"))
Log(ticker)
}
import json
import urllib.request
def main():
# HttpQuery不支持Python,可以使用urllib/urllib2库代替
info = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/public/time").read().decode('utf-8'))
Log(info)
ticker = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/market/books?instId=BTC-USDT").read().decode('utf-8'))
Log(ticker)
void main() {
auto info = json::parse(HttpQuery("https://www.okx.com/api/v5/public/time"));
Log(info);
auto ticker = json::parse(HttpQuery("https://www.okx.com/api/v5/market/books?instId=BTC-USDT"));
Log(ticker);
}
Retorna o conteúdo de um URL se o segundo parâmetroPostData
Para a stringa=1&b=2&c=abc
A forma é:POST
Como enviar. Outros exemplos:PUT
A partir de agora, o projeto está em andamento.PostData
O parâmetro é{method:'PUT', data:'a=1&b=2&c=abc'}
。
PostData
O parâmetro também pode serJSON
A linha de caracteres.
Cookies
Este parâmetro tem a forma:a=10; b=20
, cada parâmetro com uma notação;
O que você está fazendo?Headers
Este parâmetro tem a forma:User-Agent: Mobile\nContent-Type: text/html
Os parâmetros são substituídos por símbolos.\n
O que você está fazendo?
O segundo parâmetroPostData
A partir daí, a empresa desenvolveu um novo projeto de tecnologia para a construção de um novo projeto.HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc'})
Nota: Se necessário, dêHttpQuery
A função de tempo extra pode ser configurada em{method:'PUT', data:'a=1&b=2&c=abc'}
Participaçãotimeout
Atribuições (default 60 seconds)
Configure um segundo de atraso:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc', timeout:1000})
TransmissãoCookie
A string precisa de um terceiro parâmetro, mas não precisaPOST
Por favor, deixe o segundo parâmetro em branco. Quando o teste de simulação é feito, a função retorna uma string fixa porque não é possível simular o acesso à URL.Dummy Data
Pode ser usado para enviar mensagens de texto ou interagir com outras interfaces de API.
GET
Exemplos de chamadas de métodos:HttpQuery("http://www.baidu.com")
。
POST
Exemplos de chamadas de métodos:HttpQuery("http://www.163.com", "a=1&b=2&c=abc")
。
De voltaHeader
Exemplos de chamadas:
HttpQuery("http://www.baidu.com", null, "a=10; b=20", "User-Agent: Mobile\nContent-Type: text/html", true) // will return {Header: HTTP Header, Body: HTML}
HttpQuery
A função usa a configuração de um agente:
function main() {
// 本次设置代理并发送http请求,无用户名,无密码,此次http请求会通过代理发送
HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/")
// 本次设置代理并发送http请求,输入用户名和密码,仅HttpQuery当前调用生效,之后再次调用HttpQuery("http://www.baidu.com")这样不会使用代理
HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/")
}
# HttpQuery不支持Python,可以使用Python的urllib2库
void main() {
HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/");
HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/");
}
HttpQuery
Versão assíncrona da funçãoHttpQuery_Go
O que é isso?
Utilização eexchange.Go
A função é semelhante, por exemplo, acessar assincronizadamente a interface pública do exchange para obter dados de mercado agregados.
function main() {
// 创建第一个异步线程
var r1 = HttpQuery_Go("https://www.okx.com/api/v5/market/tickers?instType=SPOT")
// 创建第二个异步线程
var r2 = HttpQuery_Go("https://api.huobi.pro/market/tickers")
// 获取第一个异步线程调用的返回值
var tickers1 = r1.wait()
// 获取第二个异步线程调用的返回值
var tickers2 = r2.wait()
// 打印结果
Log("tickers1:", tickers1)
Log("tickers2:", tickers2)
}
# 不支持
// 不支持
Utilização em sistemas de retrospecçãoHttpQuery(...)
Função:
Pode ser usado em sistemas de retrospecçãoHttpQuery(...)
Enviar solicitações (suporta apenas)GET
• Limitar o uso de 20 acessos diferentes de URLs durante o retorno.HttpQuery(...)
O acesso armazena os dados da mesma URL na segunda visita.HttpQuery(...)
A função retorna dados de cache (não há mais solicitações de rede reais).
Podemos executar um programa de serviço em um servidor ou dispositivo para responder a um programa de política.HttpQuery(...)
O programa de serviço de linguagem Go usado para testar os pedidos enviados foi o seguinte:
package main
import (
"fmt"
"net/http"
"encoding/json"
)
func Handle (w http.ResponseWriter, r *http.Request) {
defer func() {
fmt.Println("req:", *r)
ret := map[string]interface{}{
"schema" : []string{"time","open","high","low","close","vol"},
"data" : []interface{}{
[]int64{1564315200000,9531300,9531300,9497060,9497060,787},
[]int64{1564316100000,9495160,9495160,9474260,9489460,338},
},
}
b, _ := json.Marshal(ret)
w.Write(b)
}()
}
func main () {
fmt.Println("listen http://localhost:9090")
http.HandleFunc("/data", Handle)
http.ListenAndServe(":9090", nil)
}
Usado para revisão de estratégiasHttpQuery(...)
Função de envio de solicitações:
function main() {
// 可以写自己运行服务程序所在设备的IP地址
Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
Log(exchange.GetAccount());
}
# HttpQuery不支持Python,可以使用Python的urllib2库
void main() {
// 可以写自己运行服务程序所在设备的IP地址
Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
Log(exchange.GetAccount());
}
Suporte para a recodificação de dados de resposta a solicitações, suporte para codificação comum.
EspecificarPostData
Parâmetros:{method: "GET",charset:"GB18030"}
O código de transmissão de dados (GB18030) pode ser implementado.
Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)
A função codifica os dados de acordo com os parâmetros transmitidos. Retorna o valor: tipo de string.
Parâmetrosalgo
Algoritmos utilizados para o cálculo do código, com configurações de suporte para:??rawdata
Os dados a serem processados.inputFormat
/outputFormat
/keyFormat
Parâmetros suportadosraw
,hex
,base64
,string
O código é o seguinte:
SekeyFormat
Para não ser nulo, use os parâmetroskey
Criptografar (HMAC) ou usar o padrãokey
Parâmetrosalgo
Configuração"sign"
Ou"signTx"
Quando você precisa de parâmetroskey
。
function main(){
Log(Encode("md5", "raw", "hex", "hello"))
Log(Encode("sha512", "raw", "base64", "hello"))
Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)"))
Log(Encode("raw", "string", "hex", "example")) // 6578616d706c65
Log(Encode("raw", "hex", "string", "6578616d706c65")) // example
}
def main():
Log(Encode("md5", "raw", "hex", "hello", "", ""))
Log(Encode("sha512", "raw", "base64", "hello", "", ""))
Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)", "", ""))
Log(Encode("raw", "string", "hex", "example", "", ""))
Log(Encode("raw", "hex", "string", "6578616d706c65", "", ""))
void main(){
Log(Encode("md5", "raw", "hex", "hello"));
Log(Encode("sha512", "raw", "base64", "hello"));
Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)"));
Log(Encode("raw", "string", "hex", "example")); // 6578616d706c65
Log(Encode("raw", "hex", "string", "6578616d706c65")); // example
}
Parâmetrosalgo
Também apoia:text.encoder.utf8
,text.decoder.utf8
,text.encoder.gbk
,text.decoder.gbk
, para codificar e decifrar as strings.
function main(){
var ret1 = Encode("text.encoder.utf8", "raw", "hex", "你好") // e4bda0e5a5bd
Log(ret1)
var ret2 = Encode("text.decoder.utf8", "hex", "string", ret1)
Log(ret2)
var ret3 = Encode("text.encoder.gbk", "raw", "hex", "你好") // c4e3bac3
Log(ret3)
var ret4 = Encode("text.decoder.gbk", "hex", "string", ret3)
Log(ret4)
}
def main():
ret1 = Encode("text.encoder.utf8", "raw", "hex", "你好", "", "") # e4bda0e5a5bd
Log(ret1)
ret2 = Encode("text.decoder.utf8", "hex", "string", ret1, "", "")
Log(ret2)
ret3 = Encode("text.encoder.gbk", "raw", "hex", "你好", "", "") # c4e3bac3
Log(ret3)
ret4 = Encode("text.decoder.gbk", "hex", "string", ret3, "", "")
Log(ret4)
void main(){
auto ret1 = Encode("text.encoder.utf8", "raw", "hex", "你好"); // e4bda0e5a5bd
Log(ret1);
auto ret2 = Encode("text.decoder.utf8", "hex", "string", ret1);
Log(ret2);
auto ret3 = Encode("text.encoder.gbk", "raw", "hex", "你好"); // c4e3bac3
Log(ret3);
auto ret4 = Encode("text.decoder.gbk", "hex", "string", ret3);
Log(ret4);
}
UnixNano()
Para obter um fuso horário de milissegundos, você pode usar o seguinte código:
function main() {
var time = UnixNano() / 1000000
Log(_N(time, 0))
}
def main():
time = UnixNano()
Log(time)
void main() {
auto time = UnixNano();
Log(time);
}
Unix()
, retorna o tempo de segundo de nível.
function main() {
var t = Unix()
Log(t)
}
def main():
t = Unix()
Log(t)
void main() {
auto t = Unix();
Log(t);
}
GetOS()
O sistema é executado através de um servidor que retorna informações do sistema onde o administrador está.
function main() {
Log("GetOS:", GetOS())
}
def main():
Log("GetOS:", GetOS())
void main() {
Log("GetOS:", GetOS());
}
Em computadores AppleMac OS
O registro de administradores executado no sistema operacional é executado:
GetOS:darwin/amd64
darwin
Ou seja,Mac OS
O nome do sistema.
MD5(String)
, valor do parâmetro: tipo de string.
function main() {
Log("MD5", MD5("hello world"))
}
def main():
Log("MD5", MD5("hello world"))
void main() {
Log("MD5", MD5("hello world"));
}
O resultado do log:
MD5 5eb63bbbe01eeed093cb22bb8f5acdc3
DBExec()
, valor de parâmetro: pode ser de tipo string, valor numérico, valor boolean, valor em branco, etc.; valor de retorno: objeto que contém o resultado da execução de uma instrução SQLite.
Funções de interface de banco de dadosDBExec()
Por meio de parâmetros de entrada, é possível operar o banco de dados em disco real (SQLite database) e realizar operações de adição, exclusão, verificação e alteração de dados no banco de dados em disco real.SQLite
O sistema de reserva de tabelas no banco de dados do disco real:kvdb
、cfg
、log
、profit
、chart
Não faça nenhuma operação nessas tabelas.DBExec()
A função só suporta disco físico.
Suporte para banco de dados em memória
ParaDBExec
Os parâmetros de uma função, seQuadradoA frase é::
Inicialmente, é mais rápido operar em um banco de dados em memória, sem escrever documentos; adequado para operações de banco de dados que não exigem a conservação permanente, como:
function main() {
var strSql = [
":CREATE TABLE TEST_TABLE(",
"TS INT PRIMARY KEY NOT NULL,",
"HIGH REAL NOT NULL,",
"OPEN REAL NOT NULL,",
"LOW REAL NOT NULL,",
"CLOSE REAL NOT NULL,",
"VOLUME REAL NOT NULL)"
].join("")
var ret = DBExec(strSql)
Log(ret)
// 增加一条数据
Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
// 查询数据
Log(DBExec(":SELECT * FROM TEST_TABLE;"))
}
def main():
arr = [
":CREATE TABLE TEST_TABLE(",
"TS INT PRIMARY KEY NOT NULL,",
"HIGH REAL NOT NULL,",
"OPEN REAL NOT NULL,",
"LOW REAL NOT NULL,",
"CLOSE REAL NOT NULL,",
"VOLUME REAL NOT NULL)"
]
strSql = ""
for i in range(len(arr)):
strSql += arr[i]
ret = DBExec(strSql)
Log(ret)
# 增加一条数据
Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
# 查询数据
Log(DBExec(":SELECT * FROM TEST_TABLE;"))
void main() {
string strSql = ":CREATE TABLE TEST_TABLE(\
TS INT PRIMARY KEY NOT NULL,\
HIGH REAL NOT NULL,\
OPEN REAL NOT NULL,\
LOW REAL NOT NULL,\
CLOSE REAL NOT NULL,\
VOLUME REAL NOT NULL)";
auto ret = DBExec(strSql);
Log(ret);
// 增加一条数据
Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"));
// 查询数据
Log(DBExec(":SELECT * FROM TEST_TABLE;"));
}
Criação de tabelas
function main() {
var strSql = [
"CREATE TABLE TEST_TABLE(",
"TS INT PRIMARY KEY NOT NULL,",
"HIGH REAL NOT NULL,",
"OPEN REAL NOT NULL,",
"LOW REAL NOT NULL,",
"CLOSE REAL NOT NULL,",
"VOLUME REAL NOT NULL)"
].join("")
var ret = DBExec(strSql)
Log(ret)
}
def main():
arr = [
"CREATE TABLE TEST_TABLE(",
"TS INT PRIMARY KEY NOT NULL,",
"HIGH REAL NOT NULL,",
"OPEN REAL NOT NULL,",
"LOW REAL NOT NULL,",
"CLOSE REAL NOT NULL,",
"VOLUME REAL NOT NULL)"
]
strSql = ""
for i in range(len(arr)):
strSql += arr[i]
ret = DBExec(strSql)
Log(ret)
void main() {
string strSql = "CREATE TABLE TEST_TABLE(\
TS INT PRIMARY KEY NOT NULL,\
HIGH REAL NOT NULL,\
OPEN REAL NOT NULL,\
LOW REAL NOT NULL,\
CLOSE REAL NOT NULL,\
VOLUME REAL NOT NULL)";
auto ret = DBExec(strSql);
Log(ret);
}
function main() {
var strSql = [
"CREATE TABLE TEST_TABLE(",
"TS INT PRIMARY KEY NOT NULL,",
"HIGH REAL NOT NULL,",
"OPEN REAL NOT NULL,",
"LOW REAL NOT NULL,",
"CLOSE REAL NOT NULL,",
"VOLUME REAL NOT NULL)"
].join("")
Log(DBExec(strSql))
// 增加一条数据
Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
// 查询数据
Log(DBExec("SELECT * FROM TEST_TABLE;"))
// 修改数据
Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000))
// 删除数据
Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110))
}
def main():
arr = [
"CREATE TABLE TEST_TABLE(",
"TS INT PRIMARY KEY NOT NULL,",
"HIGH REAL NOT NULL,",
"OPEN REAL NOT NULL,",
"LOW REAL NOT NULL,",
"CLOSE REAL NOT NULL,",
"VOLUME REAL NOT NULL)"
]
strSql = ""
for i in range(len(arr)):
strSql += arr[i]
Log(DBExec(strSql))
# 增加一条数据
Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
# 查询数据
Log(DBExec("SELECT * FROM TEST_TABLE;"))
# 修改数据
Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000))
# 删除数据
Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110))
void main() {
string strSql = "CREATE TABLE TEST_TABLE(\
TS INT PRIMARY KEY NOT NULL,\
HIGH REAL NOT NULL,\
OPEN REAL NOT NULL,\
LOW REAL NOT NULL,\
CLOSE REAL NOT NULL,\
VOLUME REAL NOT NULL)";
Log(DBExec(strSql));
// 增加一条数据
Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"));
// 查询数据
Log(DBExec("SELECT * FROM TEST_TABLE;"));
// 修改数据
Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000));
// 删除数据
Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110));
}
UUID()
, retorna um único UUID de 32 bits, que é aplicado apenas ao disco físico.
function main() {
var uuid1 = UUID()
var uuid2 = UUID()
Log(uuid1, uuid2)
}
def main():
uuid1 = UUID()
uuid2 = UUID()
Log(uuid1, uuid2)
void main() {
auto uuid1 = UUID();
auto uuid2 = UUID();
Log(uuid1, uuid2);
}
EventLoop(timeout)
E, em qualquerwebsocket
Pode ser lido ouexchange.Go
、HttpQuery_Go
Retorne depois de concluir a tarefa simultânea.timeout
Se for definido como 0 para esperar que ocorra um evento, retornará, se for maior que 0 será definido como o tempo de espera do evento, e menor que 0 retornará imediatamente o evento mais recente.null
O que é que você está fazendo?Event
Tipo de gatilho para eventos. Esta função é aplicada somente ao disco físico.
Primeira chamada no códigoEventLoop
A primeira vez que o mecanismo de interação é iniciado é após o retorno do evento.EventLoop
Chamadas, que perdem eventos anteriores. A estrutura de fila embalada pelo sistema subjacente armazenará até 500 chamadas de eventos se o programa não for chamado em tempo hábil durante a execução.EventLoop
A partir daí, o usuário pode remover o arquivo e perder o arquivo de 500 cache.EventLoop
As chamadas de funções não afetam o fundo do sistemawebsocket
A queima de cache também não é afetada.exchange.Go
O cache de funções simultâneas, por exemplo, ainda precisa usar seus próprios métodos para extrair dados.EventLoop
A função não vai voltar até que os dados já retirados não estejam em seu lugar.EventLoop
A função gerou um evento de retorno.
EventLoop
A função principal é a de notificar a camada de políticas, que recebe novos dados da rede no fundo do sistema.EventLoop
Quando a função retorna eventos, basta percorrer todas as fontes de dados.websocket
O que é a Internet?exchange.Go
Os objetos criados tentam obter dados.Links para bibliotecas。
Em funções principaismain()
O evento do fio principal é ouvido durante a chamada.JavaScript
A estratégia para escrever uma linguagem é simples:__Thread()
Os fios criados por funções podem ser chamados de funções executadas por funções, para ouvir os eventos do atual thread.
function main() {
var routine_getTicker = exchange.Go("GetTicker")
var routine_getDepth = exchange.Go("GetDepth")
var routine_getTrades = exchange.Go("GetTrades")
// Sleep(2000),如果这里使用Sleep语句,会导致之后的EventLoop函数错过之前的事件,因为等待了2秒,并发的函数
QQ89520Um problema é se a função C vai tentar novamente ou apenas uma vez.
Ai, ai!_C ((function, args...) é o padrão de 3s? Modificar o padrão para colocar diretamente _CDelay ((1000) antes de _C ((function, args...)?
lanchaiyeCluster: se você criar 1000 robôs em simultâneo, sem qualquer pressão, você pode criar vários administradores para distribuir tarefas. Há exemplos de código para criar clusters? Como criar vários administradores para descentralizar tarefas?
- O que é?Log ((talib.help (('MACD')); só pode ser usado em js, Python não tem a propriedade talib.help...
Cjz140O que é que a diferença entre a função _C (função, args...) e a função Sleep?
3263243yComo limpar o ErrorFilter após o SetErrorFilter? sem filtrar mensagens de erro.
QQ47898077Se você quiser usar uma biblioteca de terceiros, há alguma maneira de fazer isso?
QQ47898077O que deve ser preenchido pela classe pai se quisermos herdar uma nova classe definida pelo objeto da bolsa?
ethanwuHá ferramentas de depuração locais?
PenglihengO que é exange.IO (status)?
PenglihengPor que a função sell está em cinza, ou a função de representação não está disponível?
PenglihengPor que a função sell está em cinza, ou a função de representação não está disponível?
PenglihengEu não sei inglês, haha, mas gostaria de saber se o es6 é compatível.
PenglihengEu não sei inglês, haha, mas gostaria de saber se o es6 é compatível.
Don.Como escrever a linha média do volume?
ZjuturtleSe você comprar no exchange.Buy (Buy) 1000 pelo preço de mercado, o que você receberá se não for bem sucedido?
Minha filhaEssa nova fonte é linda.
hipopótamoA rede de testes da Bitmex (testnet.bitmex.com) também possui uma interface API, mas atualmente as bolsas só podem selecionar o terminal Bitmex. O endereço do documento API é https://testnet.bitmex.com/app/apiOverview. Por favor, como apoiar?
- Não, não.Var ret1 = exchanges[0].IO (("api", "future_estimated_price", "symbol=btc_usd"); Log (('ok futures estimado preço de entrega', ret1); https://dn-filebox.qbox.me/d1ed268c1e75753c5d289447d279aa9d81e41b5f.png O que é que acontece quando um usuário faz uma chamada para uma interface de outras exchanges e escreve uma mensagem de erro?
allenfrostlineA diferença entre realTicker e Ticker é que o realTicker é um software que funciona como um conjunto de ferramentas, mas que não parece ser mencionado na primeira API.
visõesOlá, como desenvolvedor de Python, o que você acha que a sua documentação API está escrevendo?
allenfrostlineGetAccount: [EAPI: Rate limit exceeded] Gostaria de saber como resolver isso?
zhjx2314Não tem suporte para StochRSI, pode ser adicionado logo?
YhfggO script está em seu próprio servidor da nuvem Ali ou no botvs cluster?
YhfggQual é a versão do Python?
FkyslyA interpretação do GetFee deve ser que o getFee retorna uma estrutura de getFee, menos um composto.
ZkwapComo usar o jss para chamar o talib?
YhfggPeça documentação Python
Wmjbs123O fundo do código para a edição de estratégias pode ser preto? Olhos pontiagudos brancos, código escrito à noite, fácil de miopia
Don.Como é que se pode configurar o sumário no bot WeChat?
Número: loucoPode-se adicionar um campo de preço igual na estrutura da ordem?
PequenoGetOrders: Retorna todos os pedidos incompletos, retorna uma estrutura de ordem de arquivo, na China Bitcoin transação ETH, retorna apenas os últimos 10 itens, aqui há uma função que retorna todos os pedidos incompletos da China Bitcoin ETH, o que significa que outras plataformas podem retornar tudo com GetOrders, só que este fantasma da China Bitcoin retorna 10 itens, o que significa que você pode usar GetOrders para retornar todos os pedidos incompletos.
YhfggA função matemática que é necessária para a probabilidade estatística, onde é que ela é usada?
JiebangQual é o significado do valor que a função $.Cross ((x, y) retorna?
A minha tia chamava-meO LogReset limpa todos os registros e pode ter um parâmetro numérico para especificar o número de registros reservados. Como é que isso elimina os últimos registos?
Edward GywA função CORRE no talib parece não ter sido transplantada ou foi perdida?
A montanha pobre de LiuyangParece que não há função de referência de indicadores!
PequenoComo é que o tempo de leitura da linha k traduz para o tempo presente?
PequenoComo escrever o número de um arquivo para removê-lo, eu acho que isso não funciona com records.remove ((records[0])
SerpenteA linha K da hora é normalmente obtida, mas como chamar ATR da linha K do dia?
SerpenteA linha K da hora é normalmente obtida, mas como chamar ATR da linha K do dia?
57278863Aprenda como os futuros tradicionais recebem preços e compras, desculpe, a base é tênue.
KirinO exemplo de negociação de futuros tradicionais!
Pequenozero, pode escrever um exemplo de negociação de futuros tradicionais?
PequenoComo imprimir o estado de armazenamento de vários blocos vazios ao mesmo tempo, como imprimir meu objeto, como obter o estado de armazenamento de vários blocos e blocos vazios, e também GetTicker, como obter o preço da semana, da próxima semana e do trimestre.
- Não, não.As bolsas de futuros podem usar o GetTicker para obter transações?
Venda em massaO StochRSI é um indicador que pode ser adicionado?
MomoxCancelOrder ((orderId) cancelar um pedido com base no número da ordem, retornar true ou false, por favor, pergunte true= a célula foi cancelada com sucesso, certo?
Momox_G(K, V) Lista de dicionários globais que podem ser salvos Este método armazena variáveis globais que podem ser usadas para compartilhar dados entre diferentes políticas?
Fluffy3dA popularidade
Zero.O registro de ganhos pode ser reiniciado com o LogProfitReset. O histórico do gráfico de ganhos anterior desaparece.
xyPode-se copiar o EA diretamente?
SJIRONMANEu sinto que a plataforma é ótima, muito boa, muito mais interação em grupo.
PequenoO que é essa língua, há material para aprender?
jxhbtcData error: uma semana sem conectar o robô.
- O quê?O banco de dados TA é apenas para calcular o preço de fechamento?
btcrobotOlá, mundo.
Sonhos pequenosA função _C tentará novamente sem pensar até obter um resultado.
Sonhos pequenosA biblioteca talib do python precisa ser instalada. https://www.botvs.com/bbs-topic/669 pode ser consultado neste post.
Sonhos pequenosSleep é o número de milissegundos em que o programa não faz nada e espera que o parâmetro seja definido, _C é a função que re-chamou o parâmetro.
Sonhos pequenosSem herança, o JS é embalado diretamente no objeto {name: "novo objeto", old_exchange : exchange[0],...... }
Sonhos pequenosO editor local, o plugin de sincronização remota, basicamente, é o editor local, o decote remoto.
Sonhos pequenosPode vir ao grupo QQ, é fácil discutir.
Sonhos pequenosEm documentos da API, o significado de cinza é que a função não tem muita explicação de expansão e mostra representados em cinza e azul.
Sonhos pequenosO ES6 está fora de suporte, ^^
Sonhos pequenosEu, descreva o problema e eu vou responder ^^
Sonhos pequenosA primeira coisa que você pode fazer é fazer um pedido de compra, mas o resultado é um erro, e você não pode fazer o pedido (ou seja, comprar, não há dinheiro suficiente!).
ZjuturtlePor exemplo, OKCoin, se o volume de compras for superior ao de empréstimos, o que será o retorno?
Sonhos pequenosA questão é: em qual bolsa eu devolveria um número de ordem no OK Futures?
Zero.Já é suportado para trocar transações em tempo de execução, sendo necessário o download do mais recente host. Suporte Bter/Poloniex API detalhada documentação Descrição da função de transação abaixo (descreva se não for possível limpar o cache do navegador e atualizar se não for possível)
Sonhos pequenosQQ, eu ajudo-te a encontrar a pergunta.
Família profissionalA lista branca precisa ser definida, e eu defino o IP do host?
Sonhos pequenosEste é o link subterrâneo Não foi criado O servidor não respondeu; O endereço IP foi configurado quando o API KEY foi solicitado?
Família profissionalIsso é embaraçoso. A política que eu poderia executar foi interrompida na era do Bitcoin, e o GetAccount não conseguiu acessar o GetAccount: Post http://api.btc38.com/v1/getMyBalance.php: read tcp 192.168.0.227:58596->211.149.148.144:80: wsarecv: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. 2017-05-23 21:08:24 Era BitEras Erro GetAccount: timeout 2017-05-23 21:08:02 Era do Bitcoin Erro GetAccount: timeout 2017-05-23 21:07:40 Bit Era Erro GetAccount: timeout 2017-05-23 21:07:20 Reiniciar É o problema da lista branca de IP???
Sonhos pequenosO servidor da bolsa não respondeu e o protocolo TCP não foi estabelecido em três apertos de mão.
Família profissionalUma tentativa de conexão falhou porque a parte conectada não respondeu adequadamente depois de um período de tempo.
Sonhos pequenosOlá! A função exchange.IO ((
Família profissionalUma tentativa de ligação falhou porque a parte ligada não respondeu adequadamente após um período de tempo,
Família profissionalA era dos bitcoins não é favorável?
Sonhos pequenoshttps://dn-filebox.qbox.me/a709b30c6cc0a3565234b9e0c99b073f7ba8b454.png O que você está fazendo é errado.
Minha filhaPor exemplo, eu queria fazer uma transação em todas as moedas do poloniex, mas apenas algumas moedas são suportadas pelo BOTvs, e o exchange.IO não parece suportar a P-Net.
Sonhos pequenosO exchange.IO pode ser chamado assim.
Minha filhaE a API que precisa de autenticação de contas?
Sonhos pequenosSe as APIs que não exigem a verificação de contas podem ser usadas com httpQuery (veja mais documentação sobre BotVS), as APIs de transações reais precisam ser acessadas.
Sonhos pequenosOs parâmetros da API podem ser transmitidos usando o HttpQuery: https://www.okcoin.com/api/v1/future_estimated_price.do?symbol=btc_usd. O post: https://www.botvs.com/bbs-topic/850
visõesMuito obrigado, espero ter uma boa e perfeita documentação API.
Sonhos pequenosPor favor, onde é que a API do realTicker foi vista?
Sonhos pequenoshttps://dn-filebox.qbox.me/fe1a6f5563ed43a5357f858ecf8a50239619228e.png A documentação da API é a linguagem JavaScript. A descrição da versão em Python é publicada no topo da página de discussão da comunidade de chat chat. Se você tem alguma dúvida, é bem-vindo a escrever.
Zero.Olá, obrigado pela sugestão, a documentação da API está sendo reconstruída.
Sonhos pequenosOlá ~ mostra que a frequência de acesso ultrapassou o limite. https://dn-filebox.qbox.me/a09498920d04cac62624b7438a058d2098d8fb00.png O objetivo é controlar a frequência de acesso à API, porque algumas exchanges definem um limite máximo de acesso, um certo tempo além de um certo número de visitas será recusado o acesso, bloqueando o endereço IP.
Sonhos pequenoshttps://dn-filebox.qbox.me/c29ab7fc279e1b758355f137907cf52dc8257df6.png O que eu escrevi pessoalmente é que os indicadores do STOCHRSI, que já foram comparados com o OK, concordam que a velocidade é um pouco lenta e precisa ser otimizada, por enquanto.
Zero.Pode escolher se o botvs fornecerá o seu servidor ou o seu servidor host, versão 2.7.5.
Sonhos pequenosAgora adicionado.
Sonhos pequenosAgora você pode configurar seu próprio estilo de fundo.
Sonhos pequenosA documentação python está sendo escrita.
Sonhos pequenosO talib é um livro que pode ser lido em português.
Hzzgood48 https://www.botvs.com/bbs-topic/276
Sonhos pequenosParece que há um exemplo na Praça da Estratégia: https://www.botvs.com/strategy/15098
Zero.Acesse a propriedade AvgPrice do Order, que é suportada pelas exchanges, e as que não são suportadas serão sempre 0
YhfggComo é que a terceira parte cita?
Zero.Se o mathjs não for capaz de satisfazer as necessidades, basta procurar políticas de importação e cópia de bibliotecas de terceiros. Para facilitar a compilação, o sistema tem apenas uma pequena quantidade de bibliotecas internas.
Sonhos pequenosNão é simpático, há um problema no grupo, pode-se M-me - eu estou basicamente online.
JiebangObrigado.
Sonhos pequenosVocê pode ver a análise de código do catálogo de transações de moeda digital na versão de notas.
Zero.Não é possível excluir o mais recente, só é possível manter alguns dos mais recentes... excluindo todos os antigos.
KirinPara obter cada posicionamento com a posição [i], a posição é um conjunto
Minha filhaexchange.GetRecords ((PERIODO_D1));
KirinO meu futuro tradicional é sempre o "GetAccount: not login", "password não errado, ou login impossível".
Zero.Por padrão, o SetContractType é necessário para obter o tipo de contrato especificado.
Zero.Como você pode ver, o verdadeiro é o valor de retorno da ação de cancelar a ordem que o exchange devolveu, mas o cancelamento real não foi cancelado, dependendo de como foi processado dentro do exchange.
Momox3q
Zero.Não, não, não, não.
XuanxuanClaro que não, isso é exclusivo do MT4.
Zero.O Javascript está em toda parte na internet.
Venda em massaO seu problema resolvido?
Zero.A maior parte do tempo, os dados podem ser transmitidos diretamente como registros ou como uma matriz de preço puro.