Не запускается код в терминале

Я только начал изучать python и слегка переделал найденный код для работы с ccxt, в результате при запуске нет совсем никакого вывода в консоли, api ключи в конфиге прописаны в чём может быть причина? Вот переделанный код

import ccxt
import time
import config
import json
import time

exchange = ccxt.ftx({
    "apiKey": config.apiKey,
    "secret": config.secret,
})
# параметр
beginPrice = 0.20   # Начальная цена интервала сетки # beginPrice + i * distance + pointProfit
endPrice = 0.30     # Конечная цена интервала сетки
distance = 20       # Ценовое расстояние каждого узла сетки
pointProfit = 50    # Маржа прибыли каждого узла сетки
amount = 0.01       # Количество заказов на узел сетки
minBalance = 0      # Минимальный остаток капитала на счете (при покупке)

# глобальная переменная
arrNet = []
arrMsg = []
acc = None

def FetchOrders (orderId, NumOfTimes, ordersList = []) :
    for i in range(NumOfTimes) :
        orders = None
        if len(ordersList) == 0:
            orders = exchange.fetch_open_orders()
        else :
            orders = ordersList
        for i in range(len(orders)):
            if orderId == orders[i]["id"]:
                return True
        time.sleep(10)
    return False

def CancelOrder (price, orderType) :
    orders = exchange.cancel_order('DOGE-PERP')
    for i in range(len(orders)) : 
        if price == orders[i]["price"] and orderType == orders[i]["type"]: 
            exchange.cancel_order(orders[i]["id"])

def checkOpenOrders (orders, ticker) :
    global arrNet, arrMsg
    for i in range(len(arrNet)) : 
        if not FetchOrders(arrNet[i]["id"], 1, orders) and arrNet[i]["status"] == "open" :
            orderId = exchange.fetch_open_orders('sell', arrNet[i]["coverPrice"], arrNet[i]["amount"], arrNet[i], ticker)
            if orderId :
                arrNet[i]["status"] = "closed"
                arrNet[i]["id"] = orderId                
            else :
                # Отозвать
                CancelOrder(arrNet[i]["coverPrice"], 'sell')
                arrMsg.append("Не удалось добавить в список!" + json.dumps(arrNet[i]))

def checkCoverOrders (orders, ticker) :
    global arrNet, arrMsg
    for i in range(len(arrNet)) : 
        if not FetchOrders(arrNet[i]["id"], 1, orders) and arrNet[i]["status"] == "closed" :
            arrNet[i]["id"] = -1
            arrNet[i]["status"] = "open"

def onTick () :
    global arrNet, arrMsg, acc

    ticker = exchange.fetch_orders()    # Получаем ордера, размещенные с вашего аккаунта.
    for i in range(len(arrNet)):       # Просмотрите все узлы сетки в соответствии с текущим рынком, найдите место, где нужно разместить купюру, и поместите купюру.
        if i != len(arrNet) - 1 and arrNet[i]["status"] == "open" and ticker['sell'] > arrNet[i]["price"] and ticker['sell'] < arrNet[i + 1]["price"]:
            acc = exchange.fetch_balance()
            if acc['free']['USD'] < minBalance :     # Если денег не хватит, остается только выпрыгнуть и ничего не делать.
                arrMsg.append("Недостаточно средств" + json.dumps(acc) + "!")
                break

            orderId = exchange.fetch_open_orders('buy', arrNet[i]["price"], arrNet[i]["amount"], arrNet[i], ticker) # Повесьте счет
            if orderId : 
                arrNet[i]["status"] = "closed"   # Обновите статус узлов сетки и другую информацию, если заказ успешно оплачен
                arrNet[i]["id"] = orderId
            else :
                # Отменить заказ
                CancelOrder(arrNet[i]["price"], ['buy'])    # Используйте функцию отмены для отмены
                arrMsg.append("Не удалось добавить в список!" + json.dumps(arrNet[i]))
    time.sleep(10)
    orders = exchange.create_order('DOGE-PERP', 'buy', amount, 'limit')    
    checkOpenOrders(orders, ticker)    # Проверьте статус всех заказов на покупку и внесите изменения.
    time.sleep(10)
    orders = exchange.create_order('DOGE-PERP', 'sell', amount, 'limit')    
    checkCoverOrders(orders, ticker)   # Проверьте статус всех заказов на продажу и внесите изменения.

    # Ниже приводится информация в строке состояния строительства. Вы можете просмотреть документацию FMZ API.
    tbl = {
        "type" : "table", 
        "title" : "Grid state",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [], 
    }    

    for i in range(len(arrNet)) : 
        tbl["rows"].append([i, json.dumps(arrNet[i])])

    errTbl = {
        "type" : "table", 
        "title" : "Record",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [], 
    }

    orderTbl = {
        "type" : "table", 
        "title" : "orders",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [],    
    }

    while len(arrMsg) > 20 : 
        arrMsg.pop(0)

    for i in range(len(arrMsg)) : 
        errTbl["rows"].append([i, json.dumps(arrMsg[i])])    

    for i in range(len(orders)) : 
        orderTbl["rows"].append([i, json.dumps(orders[i])])

def main ():         # Выполнение политики начинается здесь
    global arrNet
    for i in range(int((endPrice - beginPrice) / distance)):        # Цикл for строит структуру данных сетки в соответствии с параметрами. Это список, в котором хранится каждый узел сетки. Информация о каждом узле сетки следующая:
        arrNet.append({
            "price" : beginPrice + i * distance,                    # Цена этого узла
            "amount" : amount,                                      # Количество заказа
            "status" : "open",    # в ожидании / крышка / простаивает          # Состояние узла
            "coverPrice" : beginPrice + i * distance + pointProfit, # Цена закрытия узла
            "id" : -1,                                              # ID текущего заказа, относящегося к узлу
        })
        
    while True:    # После построения структуры данных сетки вводится основной цикл стратегии.
        onTick()   # Функция обработки в основном цикле, в основном логика обработки
        time.sleep(5) # Контрольная частота опроса

Вот на всякий случай оригинал кода


# parameter
beginPrice = 5000   # Grid interval start price
endPrice = 8000     # Grid interval end price
distance = 20       # Price distance of each grid node
pointProfit = 50    # Profit margin of each grid node
amount = 0.01       # Number of orders per grid node
minBalance = 300    # Minimum capital balance of account (when buying)

# global variable
arrNet = []
arrMsg = []
acc = None

def findOrder (orderId, NumOfTimes, ordersList = []) :
    for j in range(NumOfTimes) :
        orders = None
        if len(ordersList) == 0:
            orders = _C(exchange.GetOrders)
        else :
            orders = ordersList
        for i in range(len(orders)):
            if orderId == orders[i]["Id"]:
                return True
        Sleep(1000)
    return False

def cancelOrder (price, orderType) :
    orders = _C(exchange.GetOrders)
    for i in range(len(orders)) : 
        if price == orders[i]["Price"] and orderType == orders[i]["Type"]: 
            exchange.CancelOrder(orders[i]["Id"])
            Sleep(500)

def checkOpenOrders (orders, ticker) :
    global arrNet, arrMsg
    for i in range(len(arrNet)) : 
        if not findOrder(arrNet[i]["id"], 1, orders) and arrNet[i]["state"] == "pending" :
            orderId = exchange.Sell(arrNet[i]["coverPrice"], arrNet[i]["amount"], arrNet[i], ticker)
            if orderId :
                arrNet[i]["state"] = "cover"
                arrNet[i]["id"] = orderId                
            else :
                # Revoke
                cancelOrder(arrNet[i]["coverPrice"], ORDER_TYPE_SELL)
                arrMsg.append("Failed to list!" + json.dumps(arrNet[i]) + ", time:" + _D())

def checkCoverOrders (orders, ticker) :
    global arrNet, arrMsg
    for i in range(len(arrNet)) : 
        if not findOrder(arrNet[i]["id"], 1, orders) and arrNet[i]["state"] == "cover" :
            arrNet[i]["id"] = -1
            arrNet[i]["state"] = "idle"
            Log(arrNet[i], "The node is closed and reset to idle state.", "#FF0000")


def onTick () :
    global arrNet, arrMsg, acc

    ticker = _C(exchange.GetTicker)    # Get the latest market every time
    for i in range(len(arrNet)):       # Traverse all grid nodes, according to the current market, find out the location where the bill needs to be placed, and place the bill.
        if i != len(arrNet) - 1 and arrNet[i]["state"] == "idle" and ticker.Sell > arrNet[i]["price"] and ticker.Sell < arrNet[i + 1]["price"]:
            acc = _C(exchange.GetAccount)
            if acc.Balance < minBalance :     # If the money is not enough, we can only jump out and do nothing.
                arrMsg.append("Insufficient funds" + json.dumps(acc) + "!" + ", time:" + _D())
                break

            orderId = exchange.Buy(arrNet[i]["price"], arrNet[i]["amount"], arrNet[i], ticker) # Hang up the bill
            if orderId : 
                arrNet[i]["state"] = "pending"   # Update the status of grid nodes and other information if the order is paid successfully
                arrNet[i]["id"] = orderId
            else :
                # Cancel the order
                cancelOrder(arrNet[i]["price"], ORDER_TYPE_BUY)    # Use cancellation function to cancel
                arrMsg.append("Failed to list!" + json.dumps(arrNet[i]) + ", time:" + _D())
    Sleep(1000)
    orders = _C(exchange.GetOrders)    
    checkOpenOrders(orders, ticker)    # Check the status of all purchase orders and deal with the changes.
    Sleep(1000)
    orders = _C(exchange.GetOrders)    
    checkCoverOrders(orders, ticker)   # Check the status of all sales orders and deal with the changes.

    # The following is the construction status bar information. You can view the FMZ API documentation.
    tbl = {
        "type" : "table", 
        "title" : "Grid state",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [], 
    }    

    for i in range(len(arrNet)) : 
        tbl["rows"].append([i, json.dumps(arrNet[i])])

    errTbl = {
        "type" : "table", 
        "title" : "Record",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [], 
    }

    orderTbl = {
        "type" : "table", 
        "title" : "orders",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [],    
    }

    while len(arrMsg) > 20 : 
        arrMsg.pop(0)

    for i in range(len(arrMsg)) : 
        errTbl["rows"].append([i, json.dumps(arrMsg[i])])    

    for i in range(len(orders)) : 
        orderTbl["rows"].append([i, json.dumps(orders[i])])

    LogStatus(_D(), "\n", acc, "\n", "arrMsg length:", len(arrMsg), "\n", "`" + json.dumps([tbl, errTbl, orderTbl]) + "`")


def main ():         # Policy execution starts here
    global arrNet
    for i in range(int((endPrice - beginPrice) / distance)):        # The for loop constructs the data structure of the grid according to the parameters. It is a list that stores each grid node. The information of each grid node is as follows:
        arrNet.append({
            "price" : beginPrice + i * distance,                    # Price of this node
            "amount" : amount,                                      # Order quantity
            "state" : "idle",    # pending / cover / idle           # Node state
            "coverPrice" : beginPrice + i * distance + pointProfit, # Node closing price
            "id" : -1,                                              # ID of the current order related to the node
        })
        
    while True:    # After the grid data structure is constructed, the main cycle of the strategy is entered
        onTick()   # Processing function on main loop, mainly processing logic
        Sleep(500) # Control polling frequency
Основная дизайнерская идея стратегии - сравнить текущий список отложенных ордеров, возвращаемых интерфейсом GetOrders, со структурой данных сетки, которую мы поддерживаем. Анализируйте изменение заказа (транзакция или нет), обновляйте структуру данных сетки и выполняйте последующие операции. И заказы не будут отменены, пока транзакция не будет завершена, даже если цена отклонится, потому что на рынке цифровой валюты часто есть пины, эти пины также могут получать список пинов (если есть ограничение на количество всех связанных заказов в транзакции, она будет скорректирована).

Данные стратегии визуализируются, а функция LogStatus используется для отображения данных в строке состояния в реальном времени.

    tbl = {
        "type" : "table", 
        "title" : "Grid state",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [], 
    }    

    for i in range(len(arrNet)) : 
        tbl["rows"].append([i, json.dumps(arrNet[i])])

    errTbl = {
        "type" : "table", 
        "title" : "Record",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [], 
    }

    orderTbl = {
        "type" : "table", 
        "title" : "orders",
        "cols" : ["Node index", "detailed information"], 
        "rows" : [],    
    }```

Ответы (0 шт):