C++ tương lai cao tần số chiến lược OKEX Websocket

Tác giả:Giấc mơ nhỏ, Ngày: 24-08-2019 13:54:04
Tags:C++Lòng cheWebscoket

C++ tương lai cao tần số chiến lược OKEX Websocket

Nguyên tắc chiến lược

Chiến lược rất đơn giản, OKEX là một giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch. Chiến lược xác định hai hợp đồng, hợp đồng A, hợp đồng B. Các hợp đồng có thể đặt các mã hợp đồng khác nhau để bảo hiểm. Ví dụ, đặt hợp đồng A là hợp đồng hàng quý, hợp đồng B là hợp đồng trong tuần (cũng có thể đặt A là hợp đồng ngắn hạn, B là hợp đồng dài hạn, các định nghĩa khác là ngược lại). Hoạt động đầu cơ được chia thành hợp đồng A trống (tháng) và hợp đồng B nhiều (tương tự như hợp đồng dài hạn trống với lợi nhuận dài hạn trong hợp đồng tương lai hàng hóa, hợp đồng gần đây nhiều và hợp đồng chính) Thực hiện nhiều hợp đồng A, thực hiện hợp đồng B (như thực hiện hợp đồng ngắn hạn trong tương lai hàng hóa, thực hiện dài hạn như thế nào, thực hiện đảo ngược)

  • Đặc điểm thiết kế

    • Ngôn ngữ mã Chiến lược viết mã bằng ngôn ngữ C++, với lợi thế hiệu suất nhanh chóng.

    • Động lực: Các thị trường được điều khiển bằng OKEX websocket, giao diện nhận thị trường được đẩy ra sàn giao dịch, thu thập thị trường mới nhất đúng thời điểm, dữ liệu thị trường sử dụng dữ liệu tick dữ liệu thời gian thực với khối lượng dữ liệu nhỏ. Đối với dữ liệu tick, chiến lược đã xây dựng một trình tạo K-line đặc biệt để tổng hợp K-line dựa trên mức chênh lệch hợp đồng sau khi tính toán dữ liệu tick thu được. Các giao dịch mở và dừng của các hoạt động đầu cơ chiến lược được điều khiển bởi dữ liệu được tạo ra bởi các đối tượng loại máy tạo dòng K.

    • Kiểm soát vị trí Điều khiển vị trí sử dụng tỷ lệ vị thế được bảo hiểm tương tự như các hàng "Boffinach". Thực hiện chênh lệch lớn hơn, số lượng rủi ro lợi nhuận tương đối tăng, các vị trí được phân tán, do đó nắm bắt các vị trí chênh lệch nhỏ, các vị trí chênh lệch lớn được tăng lên một cách thích hợp.

    • Định giá ổn định: dừng lỗ dừng tăng Những người tham gia vào cuộc họp này đã nói rằng họ sẽ không làm điều gì sai trái. Chỉ cần giữ giá chênh lệch đến vị trí tăng, dừng lỗ, dừng lỗ.

    • Đưa ra thị trường, rời khỏi thị trường, thiết kế chu kỳ Các tham số NPeriod kiểm soát chu kỳ để kiểm soát một số động lực đối với chiến lược giao dịch mở.

    • Hệ thống cân bằng vị trí, hệ thống phát hiện đơn đặt hàng Các chiến lược này có hệ thống cân bằng thường xuyên. Hệ thống xác định đơn hàng.

    • Chiến lược mở rộng Các mã chiến lược được thiết kế với độ kết hợp thấp, có thể mở rộng để bảo hiểm tương lai hàng hóa hoặc được tối ưu hóa, sửa đổi hơn nữa.

    • Biểu đồ chiến lược Chiến lược tự động tạo ra biểu đồ đường K của chênh lệch, đánh dấu thông tin giao dịch liên quan.

  • Kiểm tra lại

    img

    img

    img


/*backtest
start: 2019-07-22 00:00:00
end: 2019-08-21 00:00:00
period: 1m
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD","stocks":0.1,"fee":[0.02,0.05]}]
args: [["InstrumentB","quarter"],["NPeriod",200],["LeavePeriod",100],["AddMax",3],["StopLoss",20],["StopWin",50],["OpenAmount",2]]
*/

enum State {
    STATE_NA,
    STATE_IDLE,
    STATE_HOLD_LONG,
    STATE_HOLD_SHORT,
};

string replace(string s, const string from, const string& to) {
    if(!from.empty())
        for(size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos; pos += to.size())
            s.replace(pos, from.size(), to);
    return s;
}

class BarFeeder {
    public:
        BarFeeder(int period) : _period(period) {
            _rs.Valid = true;
        }

        void feed(double price, Chart *c=nullptr, int chartIdx=0) {
            uint64_t epoch = uint64_t(Unix() / _period) * _period * 1000;
            bool newBar = false;
            if (_rs.size() == 0 || _rs[_rs.size()-1].Time < epoch) {
                Record r;
                r.Time = epoch;
                r.Open = r.High = r.Low = r.Close = price;
                _rs.push_back(r);
                if (_rs.size() > 2000) {
                    _rs.erase(_rs.begin());
                }
                newBar = true;
            } else {
                Record &r = _rs[_rs.size() - 1];
                r.High = max(r.High, price);
                r.Low = min(r.Low, price);
                r.Close = price;
            }
    
            auto bar = _rs[_rs.size()-1];
            json point = {bar.Time, bar.Open, bar.High, bar.Low, bar.Close};
            if (c != nullptr) {
               if (newBar) {
                    c->add(chartIdx, point);
                    c->reset(1000);
                } else {
                    c->add(chartIdx, point, -1);
                } 
            }
        }
        Records & get() {
            return _rs;
        }
    private:
        int _period;
        Records _rs;
};

class Hedge {
  public:
    Hedge() {
        _isCover = true;
        _needCheckOrder = true;
        _st = STATE_NA;
        for (int i = 0; i < AddMax + 1; i++) {
            if (_addArr.size() < 2) {
                _addArr.push_back((i+1)*OpenAmount);
            }
            _addArr.push_back(_addArr[_addArr.size()-1] + _addArr[_addArr.size()-2]);
        }

        _cfgStr = R"EOF(
        [{
        "extension": { "layout": "single", "col": 6, "height": "500px"},
        "rangeSelector": {"enabled": false},
        "tooltip": {"xDateFormat": "%Y-%m-%d %H:%M:%S, %A"},
        "plotOptions": {"candlestick": {"color": "#d75442", "upColor": "#6ba583"}},
        "chart":{"type":"line"},
        "title":{"text":"Spread Long"},
        "xAxis":{"title":{"text":"Date"}},
        "series":[
            {"type":"candlestick", "name":"Long Spread","data":[], "id":"dataseriesA"},
            {"type":"flags","data":[], "onSeries": "dataseriesA"}
            ]
        },
        {
        "extension": { "layout": "single", "col": 6, "height": "500px"},
        "rangeSelector": {"enabled": false},
        "tooltip": {"xDateFormat": "%Y-%m-%d %H:%M:%S, %A"},
        "plotOptions": {"candlestick": {"color": "#d75442", "upColor": "#6ba583"}},
        "chart":{"type":"line"},
        "title":{"text":"Spread Short"},
        "xAxis":{"title":{"text":"Date"}},
        "series":[
            {"type":"candlestick", "name":"Long Spread","data":[], "id":"dataseriesA"},
            {"type":"flags","data":[], "onSeries": "dataseriesA"}
            ]
        }
        ]
        )EOF";
        _c.update(_cfgStr);
        _c.reset();
    };
    
    State getState(string &symbolA, Depth &depthA, string &symbolB, Depth &depthB) {
        
        if (!_needCheckOrder && _st != STATE_NA) {
            return _st;
        }

        //Log("sync orders");
        auto orders = exchange.GetOrders();
        if (!orders.Valid) {
            return STATE_NA;
        }

        if (orders.size() > 0) {
            for (auto &order : orders) {
                exchange.CancelOrder(order.Id);
            }
            return STATE_NA;
        }
        
        Sleep(500);
        
        //Log("sync positions");
        
        auto positions = exchange.GetPosition();
        if (!positions.Valid) {
            return STATE_NA;
        }
        
        // cache orders and positions;
        _needCheckOrder = false;
        
        if (positions.size() == 0) {
            //Log("Position is empty");
            return STATE_IDLE;
        }

        
        State st[2] = {STATE_IDLE, STATE_IDLE};
        double holdAmount[2] = {0, 0};
        double holdPrice[2] = {};
        for (auto &pos : positions) {
            int idx = -1;
            if (pos.ContractType == symbolA) {
                idx = 0;
            } else if (pos.ContractType == symbolB) {
                idx = 1;
            }
            if (idx >= 0) {
                holdPrice[idx] = pos.Price;
                holdAmount[idx] += pos.Amount;
                st[idx] = pos.Type == PD_LONG || pos.Type == PD_LONG_YD ? STATE_HOLD_LONG : STATE_HOLD_SHORT;
            }
        }

        if (holdAmount[0] > holdAmount[1]) {
            st[1] = STATE_IDLE;
        } else if (holdAmount[0] < holdAmount[1]) {
            st[0] = STATE_IDLE;
        }

        if (st[0] != STATE_IDLE && st[1] != STATE_IDLE) {
            // update
            _holdPrice = _N(holdPrice[1] - holdPrice[0], 4);
            _holdAmount = holdAmount[0];
            return st[0];
        } else if (st[0] == STATE_IDLE && st[1] == STATE_IDLE) {
            return STATE_IDLE;
        } else {
            double amount = abs(holdAmount[0] - holdAmount[1]);
            auto idx_fat = st[0] == STATE_IDLE ? 1 : 0;
            if (_isCover) {
                exchange.SetContractType(st[0] == STATE_IDLE ? symbolB : symbolA);
                if (st[idx_fat] == STATE_HOLD_LONG) {
                    exchange.SetDirection("closebuy");
                    exchange.Sell((st[0] == STATE_IDLE ? depthB.Bids[0].Price: depthA.Bids[0].Price)-SlidePrice, amount);
                } else {
                    exchange.SetDirection("closesell");
                    exchange.Buy((st[0] == STATE_IDLE ? depthB.Asks[0].Price : depthA.Asks[0].Price)+SlidePrice, amount);
                }
            } else {
                exchange.SetContractType(st[0] == STATE_IDLE ? symbolA : symbolB);
                if (st[idx_fat] == STATE_HOLD_LONG) {
                    exchange.SetDirection("sell");
                    exchange.Sell((st[0] == STATE_IDLE ? depthA.Bids[0].Price : depthB.Bids[0].Price)-SlidePrice, amount);
                } else {
                    exchange.SetDirection("buy");
                    exchange.Buy((st[0] == STATE_IDLE ? depthA.Asks[0].Price : depthB.Asks[0].Price)+SlidePrice, amount);
                }
            }
            
            _needCheckOrder = true;
            
            return STATE_NA;
        }
        Log(positions);
        Panic("WTF");
    }
    bool Loop(string &symbolA, Depth &depthA, string &symbolB, Depth &depthB, string extra="") {
        
        _loopCount++;
        auto diffLong = _N(depthB.Bids[0].Price - depthA.Asks[0].Price, 4);
        auto diffShort = _N(depthB.Asks[0].Price - depthA.Bids[0].Price, 4);
        
       _feederA.feed(diffLong, &_c, 0);
       _feederB.feed(diffShort, &_c, 2);
        
        auto barsA = _feederA.get();
        auto barsB = _feederB.get();

        if (barsA.size() < max(LeavePeriod, NPeriod) + 2) {
            LogStatus(_D(), "Calc His", barsA.size());
            return true;
        }
        
        bool expired = false;
        auto seconds = Unix();
        if (seconds - _lastCache > 600) {
            _needCheckOrder = true;
            expired = true;
        }
        
        State st = getState(symbolA, depthA, symbolB, depthB);
        if (st == STATE_NA) {
            return true;
        }
        if (st == STATE_IDLE) {
            _holdPrice = 0;
        }
        // cache st
        _st = st;
        if (expired) {
            _lastCache = seconds;
        }
        
        if (Unix() - seconds > 5) {
            Log("skip this tick");
            return true;
        }
        

        LogStatus(_D(), "State: ", _state_desc[st], "Hold:", _holdPrice, "Long:", diffLong, "Short:", diffShort, "Loop:", _loopCount, extra);

        if (st == STATE_IDLE && _isCover) {
            auto account = exchange.GetAccount();
            if (account.Valid) {
                double profit = _N(exchange.GetName() == "Futures_OKCoin" ? account.Stocks + account.FrozenStocks : account.Balance + account.FrozenBalance, 8);
                LogProfit(profit, _hedgeCount > 0 ? format("Net: %f @", profit) : "");
            }
            _isCover = false;
            return true;
        }
        auto ratio = abs(diffLong - diffShort);
        bool condOpenLong = (st == STATE_IDLE || st == STATE_HOLD_LONG) && (diffLong - _countOpen * max(1.0, _holdPrice * 0.1)) > TA.Highest(barsA.High(), NPeriod) && _countOpen < AddMax;
        bool condOpenShort = (st == STATE_IDLE || st == STATE_HOLD_SHORT) && (diffShort + _countOpen * max(1.0, _holdPrice * 0.1)) < TA.Lowest(barsB.Low(), NPeriod) && _countOpen < AddMax;
        bool condCoverLong = false;
        bool condCoverShort = false;
        bool isLeave = false;
        bool isStopLoss = false;
        bool isStopWin = false;
        if (st == STATE_HOLD_LONG) {
            auto leavePrice = (diffShort + _countCover + ratio);
            isLeave = leavePrice < TA.Lowest(barsB.Low(), LeavePeriod);
            if (!isLeave) {
                isStopLoss = diffShort - _holdPrice >= StopLoss;
                if (!isStopLoss) {
                    isStopWin = _holdPrice - diffShort >= StopWin;
                    if (isStopWin) {
                        Log("Stop Win", "HOLD:", _holdPrice, "SHORT:", diffShort);
                    }
                } else {
                    Log("StopLoss", "HOLD:", _holdPrice, "SHORT:", diffShort);
                }
            } else {
                Log("Leave normally", "LeavePrice:", leavePrice);
            }
            condCoverLong = isLeave || isStopLoss || isStopWin;
        } else if (st == STATE_HOLD_SHORT) {
            auto leavePrice = (diffLong - _countCover - ratio);
            isLeave = leavePrice > TA.Highest(barsA.High(), NPeriod);
            if (!isLeave) {
                isStopLoss = _holdPrice - diffLong >= StopLoss;
                if (!isStopLoss) {
                    isStopWin = diffLong - _holdPrice >= StopWin;
                    if (isStopWin) {
                        Log("Stop Win", "HOLD:", _holdPrice, "LONG:", diffLong);
                    }
                } else {
                    Log("StopLoss", "HOLD:", _holdPrice, "LONG:", diffLong);
                }
            } else {
                Log("Leave normally", "LeavePrice:", leavePrice);
            }
            condCoverShort = isLeave || isStopLoss || isStopWin;
        }
        
        string action, color;
        double opPrice;
        int chartIdx = 0;
        if (condOpenLong) {
            // Must Increase
            if (_countOpen > 0 && diffLong <= _holdPrice) {
                return STATE_IDLE;
            }
            
            _isCover = false;
            _countOpen++;
            _countCover = 0;
            _holdPrice = diffLong;
            auto amount = _addArr[_countOpen];

            if (_countOpen > 0) {
                Log("Add Position Long", _countOpen);
            }
            exchange.SetContractType(symbolB);
            exchange.SetDirection("sell");
            exchange.Sell(depthB.Bids[0].Price-SlidePrice, amount);

            exchange.SetContractType(symbolA);
            exchange.SetDirection("buy");
            exchange.Buy(depthA.Asks[0].Price+SlidePrice, amount);
            action = "L";
            color = "blue";
            opPrice = diffLong;
            chartIdx = 1;
        } else if (condOpenShort) {
            // Must Decrease
            if (_countOpen > 0 && diffShort >= _holdPrice) {
                return STATE_IDLE;
            }
            
            _isCover = false;
            _countOpen++;
            _countCover = 0;
            _holdPrice = diffShort;
            auto amount = _addArr[_countOpen];

            if (_countOpen > 0) {
                Log("Add Position Short", _countOpen);
            }
            exchange.SetContractType(symbolA);
            exchange.SetDirection("sell");
            exchange.Sell(depthA.Bids[0].Price-SlidePrice, amount);

            exchange.SetContractType(symbolB);
            exchange.SetDirection("buy");
            exchange.Buy(depthB.Asks[0].Price+SlidePrice, amount);
            
            action = "S";
            color = "red";
            opPrice = diffShort;
            chartIdx = 3;
        } else if (condCoverLong) {
            _isCover = true;
            _countOpen = 0;
            _countCover++;
            _hedgeCount++;
            if (_countCover > 0) {
                Log("Cover Position Long", _countCover);
            }
            exchange.SetContractType(symbolB);
            exchange.SetDirection("closesell");
            exchange.Buy(depthB.Asks[0].Price+SlidePrice, _holdAmount);

            exchange.SetContractType(symbolA);
            exchange.SetDirection("closebuy");
            exchange.Sell(depthA.Bids[0].Price-SlidePrice, _holdAmount);
            
           action = "CL";
           color = "blue";
           opPrice = diffShort;
            
           chartIdx = 3;
        } else if (condCoverShort) {
            _hedgeCount++;
            _isCover = true;
            _countOpen = 0;
            _countCover++;
            if (_countCover > 0) {
                Log("Cover Position Short", _countCover);
            }
            exchange.SetContractType(symbolA);
            exchange.SetDirection("closesell");
            exchange.Buy(depthA.Asks[0].Price+SlidePrice, _holdAmount);

            exchange.SetContractType(symbolB);
            exchange.SetDirection("closebuy");
            exchange.Sell(depthB.Bids[0].Price-SlidePrice, _holdAmount);
            action = "CS";
            color = "blue";
            opPrice = diffLong;
            chartIdx = 1;
        } else {
            return true;
        }
        _needCheckOrder = true;
            
        _c.add(chartIdx, {{"x", UnixNano()/1000000}, {"title", action},  {"text", format("diff: %f", opPrice)}, {"color", color}});
        Log(st, "Long:", diffLong, "Short:", diffShort, "Hold:", _holdPrice);
        return true;
    }

  private:
    
    vector<double> _addArr;
    string _state_desc[4] = {"NA", "IDLE", "LONG", "SHORT"};
    int _countOpen = 0;
    int _countCover = 0;
    int _lastCache = 0;
    int _hedgeCount = 0;
    int _loopCount = 0;
    double _holdPrice = 0;
    BarFeeder _feederA = BarFeeder(DPeriod);
    BarFeeder _feederB = BarFeeder(DPeriod);
    State _st = STATE_NA;
    string _cfgStr;
    double _holdAmount = 0;
    bool _isCover = false;
    bool _needCheckOrder = true;
    Chart _c = Chart("{}");
    
};

inline unsigned char toHex(unsigned char x) { 
    return  x > 9 ? x + 55 : x + 48; 
}

std::string urlencode(const std::string& str) {
    std::string strTemp = "";
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (isalnum((unsigned char)str[i]) || 
            (str[i] == '-') ||
            (str[i] == '_') || 
            (str[i] == '.') || 
            (str[i] == '~'))
            strTemp += str[i];
        else if (str[i] == ' ')
            strTemp += "+";
        else
        {
            strTemp += '%';
            strTemp += toHex((unsigned char)str[i] >> 4);
            strTemp += toHex((unsigned char)str[i] % 16);
        }
    }
    return strTemp;
}

uint64_t _Time(string &s) {
    tm t_init;
    t_init.tm_year  = 70;
    t_init.tm_mon   = 0;
    t_init.tm_mday  = 1;
    t_init.tm_hour  = 0;
    t_init.tm_min   = 0;
    t_init.tm_sec   = 0;
    
    tm t;
    int year, month, day, hour, minute, second, ms;
    sscanf(s.c_str(), "%d-%d-%dT%d:%d:%d.%dZ", &year, &month, &day, &hour, &minute, &second, &ms);
    t.tm_year  = year - 1900;
    t.tm_mon   = month - 1;
    t.tm_mday  = day;
    t.tm_hour  = hour;
    t.tm_min   = minute;
    t.tm_sec   = second;
    t.tm_isdst = 0;

    return uint64_t(mktime(&t))*1000+ms-uint64_t(mktime(&t_init))*1000;
}

void main() {
    // exchange.IO("base", "https://www.okex.me");   // 测试
    if (IsSetProxy) {
        exchange.SetProxy(Proxy);
    }
    
    LogReset();
    LogProfitReset();
    SetErrorFilter("ready|timeout|500");
    Log("Init OK");
    
    string symbolA = InstrumentA;
    string symbolB = InstrumentB;
    Hedge h;
    
    if (IsVirtual()) {
        while (true) {
            exchange.SetContractType(symbolA);
            auto depthA = exchange.GetDepth();
            if (depthA.Valid) {
                exchange.SetContractType(symbolB);
                auto depthB = exchange.GetDepth();
                if (depthB.Valid) {
                    h.Loop(symbolA, depthA, symbolB, depthB);
                }
            }
        }
        return;
    }
    if (exchange.GetName() != "Futures_OKCoin") {
        Panic("only support Futures_OKCoin");
    }
    string realSymbolA = exchange.SetContractType(symbolA)["instrument"];
    string realSymbolB = exchange.SetContractType(symbolB)["instrument"];

    string qs = urlencode(json({{"op", "subscribe"}, {"args", {"futures/depth5:" + realSymbolA, "futures/depth5:" + realSymbolB}}}).dump());
    Log("try connect to websocket");
    // wss://real.OKEx.com:8443/ws/v3
    auto ws = Dial("wss://real.okex.com:8443/ws/v3|compress=gzip_raw&mode=recv&reconnect=true&payload="+qs);
    // auto ws = Dial("wss://real.okex.me:8443/ws/v3|compress=gzip_raw&mode=recv&reconnect=true&payload="+qs);
    Log("connect to websocket success");
    
    Depth depthA, depthB;
    auto fillDepth = [](json &data, Depth &d) {
        d.Valid = true;
        d.Asks.clear();
        d.Asks.push_back({atof(string(data["asks"][0][0]).c_str()), atof(string(data["asks"][0][1]).c_str())});
        d.Bids.clear();
        d.Bids.push_back({atof(string(data["bids"][0][0]).c_str()), atof(string(data["bids"][0][1]).c_str())});
    };
    string timeA;
    string timeB;
    while (true) {
        auto buf = ws.read();

        // Log("buf:", buf);   // 测试
        
        json obj;
        try {
            obj = json::parse(buf);
        } catch (json::parse_error& e) {
            Log(buf);
            Log(e.what());
            continue;
        }
        if (obj["data"].size() == 0) {
            continue;
        }
        auto data = obj["data"][0];
        string ins = data["instrument_id"];
        if (ins == realSymbolA) {
            fillDepth(data, depthA);
            timeA = data["timestamp"];
        } else if (ins == realSymbolB) {
            fillDepth(data, depthB);
            timeB = data["timestamp"];
        }
        
        if (depthA.Valid && depthB.Valid) {
            auto diffA = uint64_t(UnixNano()/1000000)-_Time(timeA);
            auto diffB = uint64_t(UnixNano()/1000000)-_Time(timeB);

            if (diffA > MaxDelay || diffB > MaxDelay) {
                continue;
            }
            h.Loop(symbolA, depthA, symbolB, depthB, format("market delay (ms): %d, %d", diffA, diffB));
        }
    }
}





Có liên quan

Thêm nữa

KhócHãy thử xem, nếu bạn có một cái bàn chạy thực sự, bạn có thể thấy nó, nhưng nếu bạn chạy một lần, bạn sẽ nhảy ra ngoài. Exchange_GetOrders: 429: {"error_message:"Too Many Requests","code":30014,"error_code":"30014","message:"Too Many Requests"} Exchange_GetOrders: 400: {"error_message": "Coin type wrong","code":30031, "error_code:" 30031","message:"Coin type wrong"} Tại sao?

Ailin/upload/asset/bb5df259b6a8148b1f65.png Mộng lớn, từ hôm qua trưa chạy đến tối không đặt hàng, từ tối chạy đến nay vẫn không đặt hàng.

Lee Hye-sangCác ổ đĩa thực được kiểm tra lại đều báo cáo lỗi phân tích json

Elvis1213/upload/asset/14bc485151de321c0a6a1.jpg chạy một thời gian rồi đột nhiên lại gặp vấn đề

Elvis1213Xin Chúa giúp tôi xem, bây giờ để khởi động báo cáo lỗi này, và ngay lập tức hàng chục trang nhật ký /upload/asset/14bfcf6f9da5f49807e68.jpg

Elvis1213Đã báo cáo lỗi này /upload/asset/14b9d3530ce1a60bde3ca.jpg, nhưng sàn giao dịch đã chọn OKEX

Những đám mây nhẹ/upload/asset/5a8be467dae6c9a52b7d.jpg Dream Big, chạy tốt ở phía trước, và sau đó xuất hiện điều này, làm thế nào để xử lý nó?

wyzcbChiến lược này có hỗ trợ EOS không?

Không quân không bao giờ là nô lệ.[json.exception.type_error.305] cannot use operator[] with a string argument with boolean; Làm thế nào để giải quyết vấn đề này?

khó khănChức năng exchange.SetContractType (symbolA) trả về lỗi với kiểu boolean.

Giấc mơ nhỏLỗi đầu tiên báo cáo là Coin type wrong, kiểm tra liệu cặp giao dịch, tiền tệ đã được đặt sai ở đâu. Lỗi thứ hai là do lỗi đầu tiên, dẫn đến thử lại thường xuyên, vượt quá giới hạn tần suất truy cập giao diện giao dịch.

Giấc mơ nhỏMã, bạn debugging, xem dữ liệu sau khi đọc giao diện ws là gì. Tìm vấn đề, tôi thử nghiệm tốt.

AilinCó phải là vấn đề với máy chủ? Nhưng máy chủ này có thể giao dịch bình thường trên OKEX

Giấc mơ nhỏĐiều đó giải thích vấn đề mạng. Không kết nối với sàn giao dịch. Không có dữ liệu được đẩy.

AilinKhông có dòng K. Chỉ có một biểu đồ chiến lược /upload/asset/ba842a27a3766766bf54.png

Giấc mơ nhỏKhi robot chạy, biểu đồ trên trang có xuất hiện không? K-line biểu đồ xuất hiện là bình thường, không kích hoạt giao dịch, nếu biểu đồ không xuất hiện, chỉ ra vấn đề thị trường, hãy kiểm tra.

Giấc mơ nhỏBạn có thể chạy qua, kiểm tra, và bạn có thể làm điều đó một lần nữa.

Lee Hye-sangTôi thấy giao diện OKX của bạn không thay đổi.

Giấc mơ nhỏChính sách này không hỗ trợ kiểm tra lại, vì nó dựa trên giao diện WS của sàn giao dịch, bạn có thể đặt nó trong mã chính sách để xem OKEX có thay đổi cổng giao diện WS trong thời gian thực hay không.

Giấc mơ nhỏThông tin này được phát đi hoàn toàn, được cho là do sự bất thường trong dữ liệu được trả về bởi giao dịch ws khi phân tích JSON.

Elvis1213Vấn đề IP đã được giải quyết.

Giấc mơ nhỏĐịa chỉ giao diện OKEX WS dường như đã thay đổi, nếu bạn muốn truy cập tài liệu OKEX, bạn có thể nhập vào địa chỉ đó.

Elvis1213Cảm ơn.

Giấc mơ nhỏChiến lược này chủ yếu được sử dụng để học tập, thực tế thận trọng, đề nghị hiểu mã, hiểu các nguyên tắc, theo thói quen giao dịch của riêng bạn và tối ưu hóa sửa đổi.

Elvis1213Cảm ơn Chúa đã triển khai thành công!

Giấc mơ nhỏChúng tôi khuyên bạn nên sử dụng máy chủ quản lý riêng.

Elvis1213Tôi chọn máy chủ công cộng /upload/asset/14b2c038dcb23dfa93b8b.jpg

Giấc mơ nhỏChọn hiện tại khi cấu hình đối tượng sàn giao dịch. /upload/asset/178df7ad9e03924f4dda.png

Những đám mây nhẹTốt, cảm ơn anh, tôi đã thử IP.

Giấc mơ nhỏĐây không phải là một báo cáo sai, đây là một sự bất thường của dữ liệu giao diện WS, một thông báo bất thường của chính sách in.

Nhà phát minh định lượngBạn có thể làm điều đó bằng cách cập nhật host.

Giấc mơ nhỏĐây không phải là báo cáo sai, đó là thông tin được in sau khi bắt gặp sự bất thường, đó là nhật ký màu xanh. Nếu không cần, bạn có thể xóa dòng đầu ra này trong mã. Có thể người quản lý là người già hơn và JSON xử lý vấn đề này. Bạn có thể cập nhật trình quản trị.

Giấc mơ nhỏThông tin báo lỗi Xem hình ảnh dưới đây hoặc sao chép và dán thông tin đi.