跳转至

教程:ccc_executor

在本教程中,让我们创建一个简单的应用程序来下订单并处理订单更新回调。

实现一个简单

的策略 SDK 使用基类 OrderSender 来保存订单更新回调函数。我们首先继承这个类并实现回调:

class MyStrategy : public OrderSender
{
public:
    using OrderSender::OrderSender;

    // implements OrderSender
    void onOrderCreated(LOrder *order) override
    {
        cout << "order created. local id = " << order->orderId << endl;
    };
    void onOrderAcked(LOrder *order) override
    {
        cout << "order ack. local id = " << order->orderId << ", id = " << order->remoteOrderId << endl;
    };
    void onOrderRejected(LOrder *order) override
    {
        cout << "order rejected. local id = " << order->orderId << endl;
    };
    void onOrderCancelCreated(LOrder *order) override
    {
        cout << "order cancel created. id = " << order->remoteOrderId << endl;
    };
    void onOrderCancelAcked(LOrder *order) override
    {
        cout << "order cancel ack. id = " << order->remoteOrderId << endl;
    };
    void onOrderCancelRejected(LOrder *order) override
    {
        cout << "order cancel rejected. id = " << order->remoteOrderId << endl;
    };
    void onOrderExec(TradeDirs side, double px, double qty, Liquidity liq, LOrder *order) override
    {
        cout << "order exec. id = " << order->remoteOrderId << (side == BUY ? " buy" : "sell") 
            << "order px: " << px << " size: " << qty << endl;
    };
    void onOrderCanceled(LOrder *order) override
    {
        cout << "order canceled. id = " << order->remoteOrderId << endl;
    };
    void onOrderClosed(LOrder *order) override
    {
        cout << "order closed. id = " << order->remoteOrderId << endl;
    };
};

现在让我们编写一些代码来加载配置文件和设置记录器。

int main(int argc, char **argv)
{
    if (argc <= 1)
    {
        cout << "Usage: ccc_executor cfg_path" << endl;
        return 0;
    }

    // load configuration
    std::time_t t = std::time(0);
    std::tm *now = std::localtime(&t);
    int date = (now->tm_year + 1900) * 10000 + (now->tm_mon + 1) * 100 + now->tm_mday;
    json cfg = loadConfig(argv[1], date);
    json &instCfg = cfg["instance"];
    instCfg["tradeDate"] = date;
    instCfg["isLive"] = true;
    instCfg["listenAllSymbol"] = true;

    // setup logger
    string instName = getJsonValue(instCfg, "name", string("instname"));
    string logPath = getJsonValue(instCfg, "log_path", string("."));
    date = instCfg["tradeDate"];
    logPath += "/" + to_string(date);
    mkdirs(logPath);
    logPath += "/inst_" + instName + ".log";
    int logLevel = getJsonValue(instCfg, "log_level", qts::log4z::LOG_LEVEL_DEBUG);
    QTS_LOG_START(logLevel, logPath);

    ConfigManager::instance()->setJsonCfg(cfg);

然后我们得到 TraderApiManager 实例和 SymbolManager 实例。这些是单例。您通过 TraderApiManager 下订单,并使用 SymbolManager 来管理交易品种。我们在这里创建一个交易品种,以便我们稍后进行交易。

    auto tradeApiMgr = TradeApiManager::instance();
    auto symMgr = SymbolManager::instance();

    string symbol = "BTCUSDT";
    string exch = "BINANCEUS";
    auto sh = symMgr->getSymbolHandler(symbol, exch);
    auto si = &sh->symbolInfo();

添加符号后,是时候启动 Apfiny Algo 框架的主循环了:

    CCTradeEngine client(cfg);
    client.initialize();
    client.async_run();

现在我们可以创建一个 MyStrategy 类的实例,并实现一些虚拟交易逻辑。在这个应用程序中,我们每 60 秒发送一次 IOC 命令。

要发送订单,我们首先创建一个 LOrder 对象,然后使用 tradeApi 发送。我们需要设置 sender 属性以接收订单更新回调。

    MyStrategy *strat = new MyStrategy();   
    TradeApi *tradeApi = tradeApiMgr->tradeApi(); // Must be called after initialize() function

    sleep(10);
    while (true)
    {
        cout << "send a random IOC order" << endl;

        LOrder *ord = new LOrder();
        ord->sender = strat;
        ord->account = 101;
        ord->use_margin = true;
        ord->margin_source = "cross";
        ord->side = BUY;
        ord->si = si;
        ord->px = 39300.0;
        ord->qty = 0.001;
        ord->remainingQty = ord->qty;
        ord->signal = 0.0;
        ord->spread = si->spread();
        ord->tif = Tif::TIF_IOC;
        ord->intention = OrderIntention::OI_AGGRESSIVE;

        tradeApi->sendOrder(ord);

        sleep(60);
    }
}

现在我们有了一个完整的交易应用程序,是时候构建、配置和运行了。

构建应用程序

该版本包含完整的源代码和用于构建它的 premake 文件。按照以下步骤构建:

cd algo_sdk/examples/ccc_executor/build_scripts
premake4 gmake
make -j 10 config=release
将生成二进制文件并复制到 algo_sdk/bin/。

创建配置文件

我们使用 JSON 文件来配置交易应用程序。该文件包含有关 api 密钥、日志路径和策略组件的信息。请更新以下示例配置中的 API 密钥信息:

{
    "instance": {
        "license_id":"",
        "license_key":"",
        "log_path": "./ccc_executor_test_01",        
        "name": "ccc_executor_test_01"
    },      
    "servers":{
        "redis_server":"127.0.0.1"                           
    }, 
    "exchanges":[
        {"exchange":"BINANCE_SWAP","trade_type":"Direct","market_data_type":"None"}
    ],
    "apikeys": {
        "BINANCE_SWAP": {
            "key": "enter your api key",
            "secret": "enter your api secert",
            "pass": "enter your api passphrase"
            }       
    },
    "fees": {
        "BINANCE_SWAP": {
            "make": 0.0,
            "take": 0.0002
        }
    },        
    "symbol_info": {
    }, 
    "symbols": [
    ],
    "samplers": [
    ],
    "pricing_models": [
    ],
    "variables": [      
    ],
    "models": [
    ],
    "strategies": [                                 
    ]
}

运行应用

Apfiny Algo 依赖于几个共享库,所以你需要先设置一些环境变量。

设置环境变量 ALGO_HOME 使用algo_sdk 的路径。例如 /data/cc/algo_sdk:

export ALGO_HOME=YOUR_ALGO_SDK_PATH

设置其他环境变量:

export TZ=UTC
export LD_LIBRARY_PATH=${ALGO_HOME}/bin:$LD_LIBRARY_PATH
export PATH=${ALGO_HOME}/ bin:$PATH

你现在可以启动应用程序了。它需要一个命令行参数,即 json 配置文件的路径。

ccc_executor ${ALGO_HOME}/examples/ccc_executor/cfg/executor_cfg.json