[TOC]
Это основная инструкция для новичков, для полной версии нашей документации API, проверьтеFMZ APIЕсть много очевидных характеристик, которые не охвачены в этом руководстве, оставленные для вас, чтобы вы обнаружили.
После изучения всего учебника вы будете знать, как работает FMZ и сможете написать некоторые базовые стратегии.
Что такое платформа FMZ?
FMZ - это автоматизированная торговая платформа для трейдеров криптовалют с поддержкой многих биржевых рынков биткоина / эфира / альткоина.
Что FMZ может сделать для вас?
Вы можете узнать, как написать свои боты ((стратегии) из нашей стратегии
Какие криптовалютные биржи поддерживает FMZ?
FMZ поддерживает почти все популярные биржи, такие какBinance
, Bitfinex
, Bitstamp
, OKEX
, Huobi
, Poloniex
, и т. д. Вы также можете торговать фьючерсами наOKEX
иBitMEX
Проверьте полный список поддержкиAPIВам нужно только написать одну стратегию и запустить ее на всех биржах без каких-либо изменений.
Какие языки программирования поддерживает FMZ?
FMZ поддерживает JavaScript, Python, C++ (JavaScript и Python рекомендуются) для кодирования ваших стратегий.
Твой API-ключ в безопасности?
Действительно, ваши API-ключи сохраняются после шифрования.
https
.Список текущих функций:
Чтобы запустить бота, вам нужно иметь стратегию, добавить обмен, сначала развернуть докер. Докер - это исполнитель вашей стратегии, работающий на вашем собственном компьютере или сервере.
Быстрый взгляд на главную страницу
Добавить обмен
Добавить вhttps://www.fmz.com/m/add-platform, или нажмитеPlatform
на этикетке.
Ваш ключ доступа и секретный ключ могут быть применены на криптовалютной бирже. API-KEY используется для торговли и получения частной информации с биржи. Мы не сохраняем API-KEY или пароли на нашем сервере.
Вы можете зарегистрироваться на FMZ
развернуть докер
FMZ не запускает ботов за вас, вам нужно развернуть докер самостоятельно в качестве исполнителя, что более гибко и безопасно, поскольку наш сервис не участвует в запуске ваших ботов.
Для окон это довольно просто, просто следуйте инструкции наhttps://www.fmz.com/m/add-node
Для Linux вы можете арендовать VPS на нашем сайте, который автоматически развернет докер.
wget www.fmz.com/dist/robot_linux_amd64.tar.gz
, команда не найдена? сначала установитьyum install wget -y
.tar -xzvf robot_linux_amd64.tar.gz
чтобы разблокировать../robot -s node.fmz.com/xxxxx -p -p yourFMZpassword
Вы должны увидеть что-то вроде2018/07/05 05:04:10 Login OK, SID: 62086, PID: 7226, Name: host.localdomain
, что означает, что все сделано.node.fmz.com/xxxxx
является уникальным для каждого пользователя, найдите свой собственный наhttps://www.fmz.com/m/add-node.ctrl + C
чтобы остановить докер.nohup ./robot -s node.fmz.com/xxxxx -p yourFMZpassword &
чтобы запустить в фоновом режиме. этот шаг также может быть выполненScreen
command.Напишите стратегию
Здесь мы будем использовать простую стратегию JavaScript в качестве демонстрации, чтобы показать, как использовать страницу редактирования.https://www.fmz.com/strategy/125482- Да. В этом учебном пособии не будет рассказано о том, как использовать JavaScript, так как вы можете найти множество учебных пособий в Интернете.
Ctrl+S
в режиме редактирования.Чтобы отправить сообщение на свой телефон, вам нужно связать телеграмму с вашим аккаунтом по адресуhttps://www.fmz.com/m/account
/*
This strategy will send a message to your telegram when the price is higher or lower than
the set price.
All strategies must have a main function as the entrance.
*/
function main() {
//change symbol,will cover the default symbol which was set when start a bot.Currency is a strategy arguments
exchange.IO("currency", Currency)
var lastPushTime = 0 //the variable of last push timestamp.
while(true){ //run a infinite loop, which is the basic structure
//_C() function can retry the request automatically after failure. not necessary. var ticker = exchange.GetTicker() is ok.
var ticker = _C(exchange.GetTicker) // for information about GetTicker, check on https://fmz-docs.readthedocs.io/en/latest/code_Instruction/Market%20API.html#getticker
if(ticker.Last > UpPrice || ticker.Last < LowPrice){ //ticker.Last represents the last deal price
if(Date.now() - lastPushTime > 300*1000){ //only push once in 5 mins, Date.now() return ms.
lastPushTime = Date.now() //update lastPushTime
Log(Currency, 'Price is: ', ticker.Last, '@') //Log the price on the bot's page and sent the message. '@' in the end means push message
}
}
Log(Currency, 'Price is: ', ticker.Last) //just log the price
Sleep(Interval*1000) //check the last price again after Interval seconds
}
}
Запустите бота
Наконец, пришло время запустить бота.
НаRobot
страница, кликнутьAdd robot
, или посетитьhttps://www.fmz.com/m/add-robotпрямо для добавления бота.
exchanges[0]
, exchanges[1]
Управление ботом
НаRobot
На странице, вы можете видеть, что бот работает.
LogProfit()
, может быть любое число, которое вы хотите.Нажмите на имя бота на странице бота для получения дополнительной информации:
Эта часть представит некоторые наиболее часто используемые API, для полной версии нашей API документации, проверьте наFMZ API- Да. Для новичков рекомендуется запустить демо-кодСтраница отладки.
2.1 Журнал
Использование: Log(msg)
Параметры:строки или цифрыОписание:Запишите сообщение на страницу журнала роботов.Возвращение:Никаких.Демонстрация:
function main() {
var msg = 'msg string'
Log(msg)
Log('hello', 'world', 123)
Log("red color message", "#FF0000")
Log("push this message to telegram!@") // won't push on debug page
}
2.2 GetTicker
Использование: exchange.GetTicker()
Параметры:Никаких.Описание:Посмотрите на текущий рынок.Возвращение:
{"Info:{}, "High":5226.69, "Low":5086.37,"Sell":5210.63, "Buy":5208.5, "Last":5208.51, "Volume":1703.1245, "OpenInterest":0, "Time":1554884195976}
Демонстрация:
function main() {
var ticker = exchange.GetTicker()
Log(ticker)
Log('Last Price: ',ticker.Last, 'Bid Price: ', ticker.Buy)
}
2.3 Получитьглубину
Использование: exchange.GetDepth()
Параметры:Никаких.Описание:Получите текущую книгу заказов на рынке.Возвращение:
{
"Info":null,
"Asks":[
{"Price":5866.38,"Amount":0.068644},
{"Price":5866.39,"Amount":0.263985},
{"Price":5866.73,"Amount":0.05},
{"Price":5866.77,"Amount":0.05},
{"Price":5867.01,"Amount":0.15},
{"Price":5875.89,"Amount":0.05},
......
]
"Bids":[
{"Price":5865.13,"Amount":0.001898},
{"Price":5865,"Amount":0.085575},
{"Price":5864.15,"Amount":0.013053},
{"Price":5863.65,"Amount":0.016727},
{"Price":5863.51,"Amount":0.128906},
{"Price":5863.15,"Amount":0.2}
......
],
"Time":1530241857399
}
Демонстрация:
function main() {
var depth = exchange.GetDepth()
Log(depth)
Log('Bid one: ', depth.Bids[0].Price, 'Ask one: ', depth.Asks[0].Price)
}
2.4 GetRecords
Использование: exchange.GetRecords()
, exchange.GetRecords(Period)
Параметры:
Имя | Тип | Обязательно | Описание |
---|---|---|---|
Период | глобальный варбл | Нет, нет. | Цикл Kline |
Все возможные параметры:PERIOD_M1
1 минута.PERIOD_M5
5 минут.PERIOD_M15
15 минут.PERIOD_M30
30 минут,PERIOD_H1
1 час,PERIOD_D1
1d.Описание:Попробуй купить "Клейн" и "Свечильник" на текущий рынок.Возвращение:
[
{"Time":1526616000000,"Open":7995,"High":8067.65,"Low":7986.6,"Close":8027.22,"Volume":9444676.27669432},
{"Time":1526619600000,"Open":8019.03,"High":8049.99,"Low":7982.78,"Close":8027,"Volume":5354251.80804935},
{"Time":1526623200000,"Open":8027.01,"High":8036.41,"Low":7955.24,"Close":7955.39,"Volume":6659842.42025361},
......
]
Демонстрация:
//A useful JavaScript example using Records to get a close array:
function main(){
var close = []
var records = exchange.GetRecords(PERIOD_H1)
Log('total bars: ', records.length)
for(var i=0;i<records.length;i++){
close.push(records[i].Close)
}
return close
}
2.5 GetAccount
Использование: exchange.GetAccount()
Параметры:Никаких.Описание:Получить информацию о счетеВозвращение:
{
"Stocks":0.38594816,// free base asset
"FrozenStocks":0, //locked base asset
"Balance":542.858308,//free quote asset
"FrozenBalance":0 //locked quote asset
"Info":{} //the raw data
}
Демонстрация:
//A useful JavaScript example of Log your account value for a certain trading pair:
function main(){
while(true){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
var price = ticker.Buy
var stocks = account.Stocks + account.FrozenStocks
var balance = account.Balance + account.FrozenBalance
var value = stocks*price + balance
Log('Account value is: ', value)
LogProfit(value)
Sleep(3000)//sleep 3000ms(3s), A loop must has a sleep, or the rate-limit of the exchange will be exceed
//when run in debug tool, add a break here
}
}
2.6 Покупать
Использование: exchange.Buy(Price, Amount)
, exchange.Buy(Price, Amount, Msg)
Параметры:
Имя | Тип | Обязательно | Описание |
---|---|---|---|
Цена | Число | Да, да. | Цена покупки предельного ордера |
Сумма | Число | Да, да. | Сумма лимитного ордера покупки |
Msg | Строка | Нет, нет. | Добавить дополнительное сообщение на странице журнала |
Описание:Отправить ордер на покупку и журнал покупки на странице ботовВозвращение:вернуть OrderID, если удалось,null
Если нет.Демонстрация:
//A useful JavaScript example of Buy for buy certain amount of bitcoin at a certain price:
function main(){
while(true){
var ticker = exchange.GetTicker()
var price = ticker.Sell
if(price >= 7000){
exchange.Buy(price+5, 1, 'BTC-USDT')
}
Sleep(3000)//Sleep 3000ms
}
}
2.7 Продать
Использование: exchange.Sell(Price, Amount)
, exchange.Sell(Price, Amount, Msg)
Параметры:
Имя | Тип | Обязательно | Описание |
---|---|---|---|
Цена | Число | Да, да. | Цена продажи предельного ордера |
Сумма | Число | Да, да. | продать сумму лимитного ордера |
Msg | Строка | Нет, нет. | Добавить дополнительное сообщение на странице журнала |
Описание:Отправить ордер на продажу и журнал продажи на страницу ботовВозвращение:вернуть OrderID, если удалось,null
Если нет.Демонстрация:
//A useful JavaScript example of Buy for buy certain amount of bitcoin at a certain price:
function main(){
while(true){
var ticker = exchange.GetTicker()
var price = ticker.Buy
if(price >= 7000){
var id = exchange.Sell(price-5, 1, 'BTC-USDT')
Log('OrderId: ', id)
}
Sleep(3000)
}
}
2.8 GetOrder
Использование: exchange.GetOrder(OrderId)
Параметры:
Имя | Тип | Обязательно | Описание |
---|---|---|---|
Приказ | Число | Да, да. | Идентификатор заказа |
Описание:Получите детали заказа по идентификатору заказа.Возвращение:
{
"Id":125723661,
"Amount":0.01,
"Price":7000,
"DealAmount":0,
"AvgPrice":0,
"Status":0, // 0:Not filled, 1:Filled, 2:Canceled
"Type":1,// 0:Buy, 1:Sell
"ContractType":"",//just for futures contract orders
"Info":{} //raw info from exchange
}
}
Демонстрация:
//A JavaScript example of using this API, which will buy until your account has 5 coins:
function main(){
while(true){
var amount = exchange.GetAccount().Stocks
var ticker = exchange.GetTicker()
var id = null
if(5-amount>0.01){
id = exchange.Buy(ticker.Sell, Math.min(10-amount,0.2))
}else{
Log('Job completed')
return //return the main function, bot will stop
}
Sleep(3000) //Sleep 3000ms
if(id){
var status = exchange.GetOrder(id).Status
if(Status == 0){
exchange.CancelOrder(id)
}
}
}
}
2.9 GetOrders
Использование: exchange.GetOrders()
Параметры:Никаких.Описание:Получите все открытые ордера на ваши торговые символы.Возвращение:Список открытых заказов, результат имеет такое же значение, какGetOrder()
[
{
"Info":{},
"Id":16387538,
"Amount":1123,
"Price":0.00012826,
"DealAmount":0,
"AvgPrice":0,
"Status":0,
"Type":1,
"ContractType":""
}
]
Демонстрация:
//A JavaScript example of using this API, which will cancel all open orders for trading symbol:
fuction CancelAll(){
var orders = exchange.GetOrders()
for(var i=0;i<orders.length,i++){
exchange.CancelOrder(orders[[i].Id) // cancel order by orderID
}
}
function main(){
CancelAll()
while(true){
//do something
Sleep(10000)
}
}
2.10 Отменить заказ
Использование: exchange.CancelOrder(OrderId)
Параметры:
Имя | Тип | Обязательно | Описание |
---|---|---|---|
Приказ | Число | Да, да. | Идентификатор заказа |
Описание:Отменить заказ по номеру заказа.Возвращение:тип bool,true
означает, что аннулирование запроса на заказ было успешно.false
означает, что аннулирование запроса не удалось.
2.11 SetContractType
Использование: exchange.SetContractType(ContractType)
Параметры:
Имя | Тип | Обязательно | Описание |
---|---|---|---|
Тип контракта | Строка | Да, да. | Тип контракта |
Описание:Установка типа контракта для торговли фьючерсами. должна быть установлена сначала, прежде чем использовать другой частный API.Возвращение:Никаких.Демонстрация:
exchange.SetContractType("this_week") //OKEX future has “this_week”, “next_week”, “quarter” , "swap"
exchange.SetContractType("XBTUSD") //BitMEX future has "XBTUSD","XBTM19",etc
2.12 Положение
Использование: exchange.GetPosition()
Параметры:Никаких.Описание:Получите информацию о текущей позиции, только для торговли фьючерсами.Возвращение:Список позиций, вернет пустой список, если у счета нет позиции.Демонстрация:
// Note: GetPosition function obtains all positions.
function main(){
exchange.SetContractType("this_week") //for OKEX future
var position = exchange.GetPosition()
if(position.length>0){
Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type, "ContractType:", position[0].ContractType)
}
}
2.13 Установка направления
Использование: exchange.SetDirection(Direction)
Параметры:
Имя | Тип | Обязательно | Описание |
---|---|---|---|
Направление | Строка | Да, да. | может бытьbuy , closebuy , sell , closesell . |
Описание:Установка типов ордеров на покупку или продажу, только для торговли фьючерсами.Возвращение:Никаких.Демонстрация:
function main(){
exchange.SetContractType("this_week");
exchange.SetMarginLevel(5) // Set the leverage to 5 times
exchange.SetDirection("buy") // Set the order type to buy long
exchange.Buy(5000, 2) //buy long at the price 1000, quantity of 2
exchange.SetDirection("closebuy")
exchange.Sell(4999, 2) //close long position
}
2.14 Другие часто используемые функции:
Узнайте больше о функциях на FMZAPI-документы
Имя | Описание | Пример |
---|---|---|
LogStatus |
Зарегистрируйте сообщение или таблицы на строке состояния ботов, будет обновляться каждый раз | LogStatus('msg') |
_C |
Функция повторного попытки | _C(exchange.GetRecords,PERIOD_H1) ,_C(exchange.GetTicker) |
_N |
Функция положения | _N(4001.512,2) ,_N(num,0) |
_G |
Глобальный словарь, который можно сохранить после перезагрузки робота. | _G('initValue', 1000);_G('initValue') |
_D |
Возвращает временную отметку | _D() , _D(1478570053241) |
TA |
Библиотека показателей TA-Lib. поддержкаMACD , EMA , KDJ И так далее... |
TA.MACD(records) |
Math |
Поддержите математическую функцию, проверьте.https://mathjs.org/ | Math.min(1,2) , Math.sqrt(2) |
Есть много стратегий обучения вhttps://www.fmz.com/square/s:tag:Study/1, что просто и легко для начинающих.
Это простая, но мощная стратегия, которая раньше зарабатывала сотни раз на реальных спотовых рынках BTC.
var floatAmountBuy = 20
var floatAmountSell = 20
var diffPrice = 3
var Interval = 3000
function CancelPendingOrders() {
var orders = _C(exchange.GetOrders);
for (var j = 0; j < orders.length; j++) {
exchange.CancelOrder(orders[j].Id, orders[j])
}
}
function GetPrice(depth) {
var price = {buy:0, sell:0}
var askAmount = 0
var bidAmount = 0
for(var i=0; i<depth.Bids.length; i++){
askAmount += depth.Asks[i].Amount
bidAmount += depth.Bids[i].Amount
if(askAmount >= floatAmountBuy && !price.buy){
price.buy = depth.Asks[i].Price
}
if(bidAmount >= floatAmountSell && !price.sell){
price.sell = depth.Bids[i].Price
}
}
if(!price.buy || !price.sell){
price = {buy:depth.Asks[depth.Asks.length-1].Price, sell:depth.Bids[depth.Bids.length-1].Price}
}
return price
}
function onTick() {
var price = GetPrice(_C(exchange.GetDepth))
var buyPrice = price.buy + 0.01
var sellPrice = price.sell - 0.01
if ((sellPrice - buyPrice) <= diffPrice){
buyPrice -= 10
sellPrice += 10
}
CancelPendingOrders()
var account = _C(exchange.GetAccount)
var amountBuy = _N((account.Balance / buyPrice-0.01), 2)
var amountSell = _N((account.Stocks), 2)
if (amountSell > 0.02) {
exchange.Sell(sellPrice, amountSell)
}
if (amountBuy > 0.02) {
exchange.Buy(buyPrice, amountBuy)
}
}
function main() {
while (true) {
onTick()
Sleep(Interval)
}
}
Классическая стратегия побега.https://www.fmz.com/strategy/103247для конфигурации. Вы можете научиться обмениваться функциями и рисовать графики из исходного кода.
var ChartCfg = {
__isStock: true,
title: {
text: 'Dual Thrust Up-Down Track'
},
yAxis: {
plotLines: [{value: 0,
color: 'red',
width: 2,
label: {
text: 'Up Track',
align: 'center'}
},
{value: 0,
color: 'green',
width: 2,
label: {
text: 'Down Track',
align: 'center'},
}
]
},
series: [{type: 'candlestick',
name: 'current cycle',
id: 'primary',
data: []
},
{type: 'flags',
onSeries: 'primary',
data: [],
}
]
};
var STATE_IDLE = 0;
var STATE_LONG = 1;
var STATE_SHORT = 2;
var State = STATE_IDLE;
var LastBarTime = 0;
var UpTrack = 0;
var BottomTrack = 0;
var chart = null;
var InitAccount = null;
var LastAccount = null;
var Counter = {
w: 0,
l: 0
};
function GetPosition(posType) {
var positions = exchange.GetPosition();
for (var i = 0; i < positions.length; i++) {
if (positions[i].Type === posType) {
return [positions[i].Price, positions[i].Amount];
}
}
return [0, 0];
}
function CancelPendingOrders() {
while (true) {
var orders = exchange.GetOrders();
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
Sleep(Interval);
}
if (orders.length === 0) {
break;
}
}
}
function Trade(currentState, nextState) {
var pfn = nextState === STATE_LONG ? exchange.Buy : exchange.Sell;
if (currentState !== STATE_IDLE) {
exchange.SetDirection(currentState === STATE_LONG ? "closebuy" : "closesell");
while (true) {
var amount = GetPosition(currentState === STATE_LONG ? PD_LONG : PD_SHORT)[1];
if (amount === 0) {
break;
}
// pfn(amount);
pfn(nextState === STATE_LONG ? _C(exchange.GetTicker).Sell * 1.001 : _C(exchange.GetTicker).Buy * 0.999, amount);
Sleep(Interval);
CancelPendingOrders();
}
var account = exchange.GetAccount();
if (account.Stocks > LastAccount.Stocks) {
Counter.w++;
} else {
Counter.l++;
}
LogProfit(_N(account.Stocks - InitAccount.Stocks), "Profit rate:", _N((account.Stocks - InitAccount.Stocks) * 100 / InitAccount.Stocks) + '%');
LastAccount = account;
}
exchange.SetDirection(nextState === STATE_LONG ? "buy" : "sell");
while (true) {
var pos = GetPosition(nextState === STATE_LONG ? PD_LONG : PD_SHORT);
if (pos[1] >= AmountOP) {
Log("Average Price", pos[0], "amount:", pos[1]);
break;
}
// pfn(AmountOP-pos[1]);
pfn(nextState === STATE_LONG ? _C(exchange.GetTicker).Sell * 1.001 : _C(exchange.GetTicker).Buy * 0.999, AmountOP-pos[1]);
Sleep(Interval);
CancelPendingOrders();
}
}
function onTick(exchange) {
var records = exchange.GetRecords();
if (!records || records.length <= NPeriod) {
return;
}
var Bar = records[records.length - 1];
if (LastBarTime !== Bar.Time) {
var HH = TA.Highest(records, NPeriod, 'High');
var HC = TA.Highest(records, NPeriod, 'Close');
var LL = TA.Lowest(records, NPeriod, 'Low');
var LC = TA.Lowest(records, NPeriod, 'Close');
var Range = Math.max(HH - LC, HC - LL);
UpTrack = _N(Bar.Open + (Ks * Range));
DownTrack = _N(Bar.Open - (Kx * Range));
if (LastBarTime > 0) {
var PreBar = records[records.length - 2];
chart.add(0, [PreBar.Time, PreBar.Open, PreBar.High, PreBar.Low, PreBar.Close], -1);
} else {
for (var i = Math.min(records.length, NPeriod * 3); i > 1; i--) {
var b = records[records.length - i];
chart.add(0, [b.Time, b.Open, b.High, b.Low, b.Close]);
}
}
chart.add(0, [Bar.Time, Bar.Open, Bar.High, Bar.Low, Bar.Close]);
ChartCfg.yAxis.plotLines[0].value = UpTrack;
ChartCfg.yAxis.plotLines[1].value = DownTrack;
ChartCfg.subtitle = {
text: 'Up Track: ' + UpTrack + ' Down Track: ' + DownTrack
};
chart.update(ChartCfg);
chart.reset(PeriodShow);
LastBarTime = Bar.Time;
} else {
chart.add(0, [Bar.Time, Bar.Open, Bar.High, Bar.Low, Bar.Close], -1);
}
LogStatus("Price:", Bar.Close, "Up:", UpTrack, "Down:", DownTrack, "Wins: ", Counter.w, "Losses:", Counter.l, "Date:", new Date());
var msg;
if (State === STATE_IDLE || State === STATE_SHORT) {
if (Bar.Close >= UpTrack) {
msg = 'Long Price: ' + Bar.Close + ' Up Track:' + UpTrack;
Log(msg);
Trade(State, STATE_LONG);
State = STATE_LONG;
chart.add(1, {x:Bar.Time, color: 'red', shape: 'flag', title: 'Long', text: msg});
}
}
if (State === STATE_IDLE || State === STATE_LONG) {
if (Bar.Close <= DownTrack) {
msg = 'Short Price: ' + Bar.Close + ' Down Track:' + DownTrack;
Log(msg);
Trade(State, STATE_SHORT);
chart.add(1, {x:Bar.Time, color: 'green', shape: 'circlepin', title: 'Short', text: msg});
State = STATE_SHORT;
}
}
}
function onexit() {
var pos = exchange.GetPosition();
if (pos.length > 0) {
Log("Warning, has positions when exiting", pos);
}
}
function main() {
if (exchange.GetName() !== 'Futures_OKCoin') {
throw "Only support OKEX features";
}
exchange.SetRate(1);
exchange.SetContractType(["this_week", "next_week", "quarter"][ContractTypeIdx]);
exchange.SetMarginLevel([10, 20][MarginLevelIdx]);
if (exchange.GetPosition().length > 0) {
throw "Can't have Positions when start.";}
CancelPendingOrders();
InitAccount = LastAccount = exchange.GetAccount();
LoopInterval = Math.min(1, LoopInterval);
Log('Exchange Name:', exchange.GetName(), InitAccount);
LogStatus("Ready...");
LogProfitReset();
chart = Chart(ChartCfg);
chart.reset();
LoopInterval = Math.max(LoopInterval, 1);
while (true) {
onTick(exchange);
Sleep(LoopInterval * 1000);
}
}
Травапродолжайте обновлять этот пост, не стесняйтесь задавать вопросы