资源加载中... loading...

Trade

exchange.Buy

exchange.Buy()函数用于下买单。Buy()函数是交易所对象{@var/EXCHANGE exchange}的成员函数。 Buy()函数操作交易所对象exchange绑定的交易所账户,exchange对象的成员函数(方法)的用途只和exchange相关,文档之后不再赘述。

下单成功返回订单Id,下单失败返回空值。 string、空值

exchange.Buy(price, amount) exchange.Buy(price, amount, …args)

price参数用于设置订单价格。 price true number amount参数用于设置订单量。 amount true number 扩展参数,可以输出附带信息到这条下单日志中,arg参数可以传多个。 arg false string、number、bool、object、array、空值等系统支持的任意类型

function main() {
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    // 设置合约代码
    exchange.SetContractType("rb888")
    // 设置下单方向
    exchange.SetDirection("buy")

    // 注意,这里的下单价格100为举例,具体测试的时候可以自行设置、改动
    var id = exchange.Buy(100, 1)
    Log("id:", id)
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    exchange.SetContractType("rb888")
    exchange.SetDirection("buy")
    
    id = exchange.Buy(100, 1)
    Log("id:", id)
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    exchange.SetContractType("rb888");
    exchange.SetDirection("buy");
    
    auto id = exchange.Buy(100, 1);
    Log("id:", id);
}

exchange.Buy()返回的订单编号,可用于查询订单信息和取消订单。

function main() {
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    // 设置合约代码
    exchange.SetContractType("rb888")
    // 设置下单方向
    exchange.SetDirection("buy")  
    
    // 下单价格参数传-1即为市价单
    var id = exchange.Buy(-1, 1)
    Log("id:", id)
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    exchange.SetContractType("rb888")
    exchange.SetDirection("buy")  
    
    id = exchange.Buy(-1, 1)
    Log("id:", id)
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    exchange.SetContractType("rb888");
    exchange.SetDirection("buy");
    
    auto id = exchange.Buy(-1, 1);
    Log("id:", id);
}

商品期货、股票证券除了使用市价单(价格参数传-1,实际是系统使用了一个较高的买入价或者较低的卖出价来确保成交),还可以用限价单方式下单。 可以使用一个较大的滑价,确保和对手盘成交,参看exchange.Sell中的范例。

期货合约下单时必须注意交易方向是否设置正确,如果交易方向和交易函数不匹配会报错。 参考:{@fun/Futures/exchange.SetDirection exchange.SetDirection} 参数price设置为-1用于下市价单,回测系统、实盘环境均支持市价单。 股票证券下单: 下单量为股票股数,并非股票手数(在股票证券交易所对象中如无特殊说明,相关的量均为股票股数)。下单量需要符合股票信息中的每手股数要求。 例如,02333.HK港股长城汽车,每手500股。下单量必须是500的整倍数。601633.SH为A股长城汽车,每手100股。下单量必须是100的整倍数。 每手股数可以从SetContractType函数返回的数据结构中获取(VolumeMultiple字段)。也可以从GetTicker()函数返回的数据结构中的Info属性中获取(LotSize字段)。

{@fun/Trade/exchange.Sell exchange.Sell}, {@fun/Futures/exchange.SetContractType exchange.SetContractType}, {@fun/Futures/exchange.SetDirection exchange.SetDirection}

exchange.Sell

exchange.Sell()函数用于下卖单。

下单成功返回订单Id,下单失败返回空值。 参考{@fun/Trade/exchange.Buy exchange.Buy}。 string、空值

exchange.Sell(price, amount) exchange.Sell(price, amount, …args)

price参数用于设置订单价格。 price true number amount参数用于设置订单量。 amount true number 扩展参数,可以输出附带信息到这条下单日志中,arg参数可以传多个。 arg false string、number、bool、object、array、空值等系统支持的任意类型

function main(){
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    // 设置合约代码
    exchange.SetContractType("rb888")
    // 设置下单方向
    exchange.SetDirection("sell")
    
    // 注意,这里的下单价格100为举例,具体测试的时候可以自行设置、改动
    var id = exchange.Sell(100, 1)
    Log("id:", id)
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    exchange.SetContractType("rb888")
    exchange.SetDirection("sell")
    
    id = exchange.Sell(100, 1)
    Log("id:", id)
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    exchange.SetContractType("rb888");
    exchange.SetDirection("sell");
    
    auto id = exchange.Sell(100, 1);
    Log("id:", id);
}

exchange.Sell()返回的订单编号,可用于查询订单信息和取消订单。

function main() {
    while(true) {
        if (exchange.IO("status")) {
            // 设置当前合约为 rb2001 , 测试的时候按回测时间设置合适的合约
            exchange.SetContractType("rb2001")               
            exchange.SetDirection("buy")
            // 获取当前行情
            var ticker = exchange.GetTicker()                
            // 拿到当前卖一价格
            var currSell1Price = ticker.Sell                 
            // 加50元滑价,即为比出价卖出的挂单高50,要求买入1手
            var id = exchange.Buy(currSell1Price + 50, 1)    
            Log(exchange.GetOrder(id))
            break
        } else {
            Log("未连接")
        }
    }
}
def main():
    while True:
        if exchange.IO("status"):
            exchange.SetContractType("rb2001")
            exchange.SetDirection("buy")
            ticker = exchange.GetTicker()
            currSell1Price = ticker["Sell"]
            id = exchange.Buy(currSell1Price + 50, 1)
            Log(exchange.GetOrder(id))
            break
        else :
            Log("未连接")
void main() {
    while(true) {
        if(exchange.IO("status") == 1) {
            exchange.SetContractType("rb2001");
            exchange.SetDirection("buy");
            auto ticker = exchange.GetTicker();
            auto currSell1Price = ticker.Sell;
            auto id = exchange.Buy(currSell1Price + 50, 1);
            Log(exchange.GetOrder(id));
            break;
        } else {
            Log("未连接");
        }
    }
}

商品期货除了使用市价单还可以用限价单方式下单,可以使用一个较大的滑价确保和对手盘成交。

期货合约下单时必须注意交易方向是否设置正确,如果交易方向和交易函数不匹配会报错。 参考:{@fun/Futures/exchange.SetDirection exchange.SetDirection} 参数price设置为-1用于下市价单,回测系统、实盘环境均支持市价单。 下单量为股票股数,并非股票手数(在股票证券交易所对象中如无特殊说明,相关的量均为股票股数)。下单量需要符合股票信息中的每手股数要求。 参考{@fun/Trade/exchange.Buy exchange.Buy}。

{@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Futures/exchange.SetContractType exchange.SetContractType}, {@fun/Futures/exchange.SetDirection exchange.SetDirection}

exchange.CreateOrder

exchange.CreateOrder()函数用于下单。

下单成功返回订单Id,下单失败返回空值。 string、空值

exchange.CreateOrder(symbol, side, price, amount) exchange.CreateOrder(symbol, side, price, amount, …args)

参数symbol用于指定订单的合约代码。传空字符串""时默认以当前设置的合约代码下单。

symbol true string side参数的可选值为:buyclosebuysellclosesellclosesell_todayclosebuy_todaybuy表示开多仓,closebuy表示平多昨仓,sell表示开空仓,closesell表示平空昨仓,closebuy_today表示平多今仓,closesell_today表示平空今仓。

side true string price参数用于设置订单价格。

price true number amount参数用于设置订单量。

amount true number 扩展参数,可以输出附带信息到这条下单日志中,arg参数可以传多个。 arg false string、number、bool、object、array、空值等系统支持的任意类型

function main() {
    while(!exchange.IO("status")) {
        Sleep(1000)
    }
    // 调用CreateOrder函数下单
    var id = exchange.CreateOrder("rb2410", "buy", 3500, 1)
    Log(id)
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    id = exchange.CreateOrder("rb2410", "buy", 3500, 1)
    Log(id)
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    auto id = exchange.CreateOrder("rb2410", "buy", 3500, 1);
    Log(id);
}

商品期货交易所对象调用exchange.CreateOrder()函数下单。

{@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Trade/exchange.Sell exchange.Sell}

exchange.CancelOrder

exchange.CancelOrder()函数用于取消订单。

exchange.CancelOrder()函数返回真值,例如true表示取消订单请求发送成功, 返回假值,例如false表示取消订单请求发送失败。返回值只是代表发送请求成功或失败,判断交易所是否取消订单, 可以调用exchange.GetOrders()判断。 bool

exchange.CancelOrder(orderId) exchange.CancelOrder(orderId, …args)

orderId参数用于指定所要取消的订单。 orderId true string 扩展参数,可以输出附带信息到这条撤单日志中,arg参数可以传多个。 arg false string、number、bool、object、array、空值等系统支持的任意类型

function main(){
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    // 设置合约代码
    exchange.SetContractType("rb888")
    // 设置下单方向
    exchange.SetDirection("sell")
    
    // 下单价格只是举例,较大的价格不会成交,订单会处于订单薄中待成交状态,具体测试可以自行调整价格
    var id = exchange.Sell(99999, 1)
    exchange.CancelOrder(id)
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    exchange.SetContractType("rb888")
    exchange.SetDirection("sell")
    
    id = exchange.Sell(99999, 1)
    exchange.CancelOrder(id)
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    exchange.SetContractType("rb888");
    exchange.SetDirection("sell");
    
    auto id = exchange.Sell(99999, 1);
    exchange.CancelOrder(id);
}

撤销订单。

function main() {
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    // 设置合约代码
    exchange.SetContractType("rb888")
    // 设置下单方向
    exchange.SetDirection("sell")    

    Log("数据1", "数据2", "数据3", "...")
    var data2 = 200
    // 下单价格只是举例,较大的价格不会成交,订单会处于订单薄中待成交状态,具体测试可以自行调整价格
    var id = exchange.Sell(100000, 0.1, "附带数据1", data2, "...")
    exchange.CancelOrder(id, "附带数据1", data2, "...")
    LogProfit(100, "附带数据1", data2, "...")
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    exchange.SetContractType("rb888")
    exchange.SetDirection("sell")
    
    Log("数据1", "数据2", "数据3", "...")
    data2 = 200
    id = exchange.Sell(100000, 0.1, "附带数据1", data2, "...")
    exchange.CancelOrder(id, "附带数据1", data2, "...")
    LogProfit(100, "附带数据1", data2, "...")
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    exchange.SetContractType("rb888");
    exchange.SetDirection("sell");
    
    Log("数据1", "数据2", "数据3", "...");
    int data2 = 200;
    auto id = exchange.Sell(100000, 0.1, "附带数据1", data2, "...");
    exchange.CancelOrder(id, "附带数据1", data2, "...");
    LogProfit(100, "附带数据1", data2, "...");
}

优宽量化的API函数中可以产生日志输出的函数例如:Log(...)exchange.Buy(Price, Amount)exchange.CancelOrder(Id)等都可以在必要参数后跟一些附带输出参数。 例如:exchange.CancelOrder(orders[j].Id, orders[j]),这样就是在取消Id为orders[j].Id的这个订单时附带输出这个订单的信息,即orders[j]这个Order结构。

参数orderId的类型为字符串类型。

{@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Trade/exchange.Sell exchange.Sell}, {@fun/Trade/exchange.GetOrders exchange.GetOrders}

exchange.GetOrder

exchange.GetOrder()函数用于获取订单信息。

根据订单号查询订单详情,查询成功返回{@struct/Order Order}结构,查询失败返回空值。 {@struct/Order Order}、空值

exchange.GetOrder(orderId)

orderId参数用于指定所要查询的订单。 orderId true string

function main(){
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    // 设置合约代码
    exchange.SetContractType("rb888")
    // 设置下单方向
    exchange.SetDirection("sell")
    
    // 下单价格只是举例,较大的价格不会成交,订单会处于订单薄中待成交状态,具体测试可以自行调整价格
    var id = exchange.Sell(99999, 1)
    // 参数id为订单号码,需填入你想要查询的订单的号码
    var order = exchange.GetOrder(id)      
    Log("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:",
        order.DealAmount, "Status:", order.Status, "Type:", order.Type)
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    exchange.SetContractType("rb888")
    exchange.SetDirection("sell")
    
    id = exchange.Sell(99999, 1)
    order = exchange.GetOrder(id)
    Log("Id:", order["Id"], "Price:", order["Price"], "Amount:", order["Amount"], "DealAmount:", 
        order["DealAmount"], "Status:", order["Status"], "Type:", order["Type"])
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    exchange.SetContractType("rb888");
    exchange.SetDirection("sell");
    
    auto id = exchange.Sell(99999, 1);
    auto order = exchange.GetOrder(id);
    Log("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:", 
        order.DealAmount, "Status:", order.Status, "Type:", order.Type);
}

根据具体订单Id查询订单详细信息。

返回值为{@struct/Order Order}结构。

{@struct/Order Order}, {@fun/Trade/exchange.GetOrders exchange.GetOrders}

exchange.GetOrders

exchange.GetOrders()函数用于获取所有合约的未完成的订单,支持查询指定合约的未完成订单。

exchange.GetOrders()函数请求数据成功时返回{@struct/Order Order}结构数组,请求数据失败时返回空值。 {@struct/Order Order}数组、空值

exchange.GetOrders() exchange.GetOrders(symbol)

参数symbol用于指定所要查询的订单数据的合约代码。不传该参数时默认请求所有合约的当前未完成订单数据。

symbol false string

function main(){
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    // 设置合约代码
    exchange.SetContractType("rb888")
    // 设置下单方向
    exchange.SetDirection("sell")
    
    // 下单价格只是举例,较大的价格不会成交,订单会处于订单薄中待成交状态,具体测试可以自行调整价格
    exchange.Sell(99999, 1)
    exchange.Sell(88888, 1)
    var orders = exchange.GetOrders()
    Log("未完成订单一的信息,ID:", orders[0].Id, "Price:", orders[0].Price, "Amount:", orders[0].Amount,
        "DealAmount:", orders[0].DealAmount, "Type:", orders[0].Type, "Symbol:", orders[0].Symbol)
    Log("未完成订单二的信息,ID:", orders[1].Id, "Price:", orders[1].Price, "Amount:", orders[1].Amount,
        "DealAmount:", orders[1].DealAmount, "Type:", orders[1].Type, "Symbol:", orders[1].Symbol)
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    exchange.SetContractType("rb888")
    exchange.SetDirection("sell")
    
    exchange.Sell(99999, 1)
    exchange.Sell(88888, 1)
    orders = exchange.GetOrders()
    Log("未完成订单一的信息,ID:", orders[0]["Id"], "Price:", orders[0]["Price"], "Amount:", orders[0]["Amount"], 
        "DealAmount:", orders[0]["DealAmount"], "Type:", orders[0]["Type"], "Symbol:", orders[0]["Symbol"])
    Log("未完成订单二的信息,ID:", orders[1]["Id"], "Price:", orders[1]["Price"], "Amount:", orders[1]["Amount"],
        "DealAmount:", orders[1]["DealAmount"], "Type:", orders[1]["Type"], "Symbol:", orders[1]["Symbol"])
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    exchange.SetContractType("rb888");
    exchange.SetDirection("sell");
    
    exchange.Sell(99999, 1);
    exchange.Sell(88888, 1);
    auto orders = exchange.GetOrders();
    Log("未完成订单一的信息,ID:", orders[0].Id, "Price:", orders[0].Price, "Amount:", orders[0].Amount, 
        "DealAmount:", orders[0].DealAmount, "Type:", orders[0].Type, "Symbol:", orders[0].Symbol);
    Log("未完成订单二的信息,ID:", orders[1].Id, "Price:", orders[1].Price, "Amount:", orders[1].Amount,
        "DealAmount:", orders[1].DealAmount, "Type:", orders[1].Type, "Symbol:", orders[1].Symbol);
}

以一个很高的价格下单,然后查询未完成订单信息。

/*backtest
start: 2020-06-17 10:00:00
end: 2020-06-18 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/

function main() {
    var contractTypeList = ["MA009", "rb2010", "i2009"]
    while (true) {
        if (exchange.IO("status")) {
            for (var i = 0; i < contractTypeList.length; i++) {
                var ret = exchange.SetContractType(contractTypeList[i])
                var ticker = exchange.GetTicker()
                exchange.SetDirection("sell")
                var id = exchange.Sell(ticker.Sell + 5, 1)
                Log(contractTypeList[i], "开空仓订单ID:", id)
            }
            var orders = exchange.GetOrders()
            for (var j = 0; j < orders.length; j++) {
                Log(orders[j])
            }
            break
        } else {
            LogStatus(_D(), "未连接")
        }
    }
}
'''backtest
start: 2020-06-17 10:00:00
end: 2020-06-18 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
'''

def main():
    contractTypeList = ["MA009", "rb2010", "i2009"]
    while True:
        if exchange.IO("status"):
            for i in range(len(contractTypeList)):
                ret = exchange.SetContractType(contractTypeList[i])
                ticker = exchange.GetTicker()
                exchange.SetDirection("sell")
                id = exchange.Sell(ticker["Sell"] + 5, 1)
                Log(contractTypeList[i], "开空仓订单ID:", id)
            
            orders = exchange.GetOrders()
            for i in range(len(orders)):
                Log(orders[i])                            
            break
        else:
            LogStatus(_D(), "未连接")
/*backtest
start: 2020-06-17 10:00:00
end: 2020-06-18 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/

void main() {
    vector<string> contractTypeList = {"MA009", "rb2010", "i2009"};
    while (true) {
        if (exchange.IO("status") == 1) {
            for (int i = 0 ; i < contractTypeList.size(); i++) {
                auto ret = exchange.SetContractType(contractTypeList[i]);
                auto ticker = exchange.GetTicker();
                exchange.SetDirection("sell");
                auto id = exchange.Sell(ticker.Sell + 5.0, 1);
                Log(contractTypeList[i], "开空仓订单ID:", id);
            }
            auto orders = exchange.GetOrders();
            for (int j = 0; j < orders.size(); j++) {
                Log(orders[j]);
            }
            break;
        } else {
            LogStatus(_D(), "未完成");
        }
    } 
}

exchange.GetOrders()函数在商品期货、股票证券中获取的是所有未完成订单。 在商品期货中exchange.GetOrders()函数获取的订单与当前设置的合约无关。可以使用以下例子进行回测、模拟盘、实盘测试。

当交易所对象exchange代表的账户没有挂单(处于未成交状态的活动订单)时,调用exchange.GetOrders()函数返回空数组,即:[]exchange.GetOrders()函数不依赖于当前合约代码设置,不传symbol参数时获取所有合约的未完成订单。

{@struct/Order Order}, {@fun/Trade/exchange.GetOrder exchange.GetOrder}

exchange.GetHistoryOrders

exchange.GetHistoryOrders()函数用于获取当前交易日内的所有合约的历史订单,支持查询指定合约的历史订单。

exchange.GetHistoryOrders()函数请求数据成功时返回{@struct/Order Order}结构数组,请求数据失败时返回空值。 {@struct/Order Order}数组、空值

exchange.GetHistoryOrders() exchange.GetHistoryOrders(symbol)

symbol参数用来指定所要获取的历史订单的合约名称。

symbol false string

function main(){
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    
    var orders = exchange.GetHistoryOrders()
    Log(orders)
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    
    orders = exchange.GetHistoryOrders()
    Log(orders)
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    
    auto orders = exchange.GetHistoryOrders();
    Log(orders);
}

注意:exchange.GetHistoryOrders()函数不依赖于当前合约代码设置,不传symbol参数时获取当前交易日所有合约的历史订单。传入symbol参数指定获取当前交易日具体合约的历史订单。

{@struct/Order Order}, {@fun/Trade/exchange.GetOrder exchange.GetOrder}, {@fun/Trade/exchange.GetOrders exchange.GetOrders}

exchange.SetPrecision

exchange.SetPrecision()函数用于设置exchange交易所对象的价格下单量的精度,设置后系统会自动忽略数据多余的部分。

exchange.SetPrecision(pricePrecision, amountPrecision)

pricePrecision参数用来控制价格数据的精度。 pricePrecision true number amountPrecision参数用来控制下单量数据的精度。 amountPrecision true number

function main(){
    // 设置价格小数位精度为2位,品种下单量小数位精度为3位
    exchange.SetPrecision(2, 3)
}
def main():
    exchange.SetPrecision(2, 3)
void main() {
    exchange.SetPrecision(2, 3);
}

设置价格精度、下单量精度。

回测系统不支持该函数,回测系统的数值精度会自动处理。 pricePrecisionamountPrecision都必须是整型的数值。

{@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Trade/exchange.Sell exchange.Sell}

exchange.SetRate

设置交易所对象当前的汇率。

exchange.SetRate(rate)

rate参数用于指定转换汇率。 rate true number

function main(){
    // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
    while (!exchange.IO("status")) {
        Sleep(1000)
    }
    // 设置合约代码
    exchange.SetContractType("rb888")
    
    // 设置汇率之前打印行情数据
    Log(exchange.GetTicker())
    // 设置汇率转换
    exchange.SetRate(7)
    Log(exchange.GetTicker())
    // 设置为1,不转换
    exchange.SetRate(1)
    Log(exchange.GetTicker())
}
def main():
    while not exchange.IO("status"):
        Sleep(1000)
    exchange.SetContractType("rb888")
    
    Log(exchange.GetTicker())
    exchange.SetRate(7)
    Log(exchange.GetTicker())
    exchange.SetRate(1)
    Log(exchange.GetTicker())
void main() {
    while (exchange.IO("status") == 0) {
        Sleep(1000);
    }
    exchange.SetContractType("rb888");
    
    Log(exchange.GetTicker());
    exchange.SetRate(7);
    Log(exchange.GetTicker());
    exchange.SetRate(1);
    Log(exchange.GetTicker());
}

设置交易所对象当前的汇率。

如果使用exchange.SetRate()函数设置过一个汇率值,例如设置为7。 那么当前exchange这个交易所对象代表的交易所的行情、深度、下单价格等所有价格信息,都会被乘以设置的汇率7,进行转换。 例如exchange是以美元为计价货币的交易所。执行exchange.SetRate(7)之后,实盘所有价格都会被乘7转换成接近CNY计价的价格。

{@fun/Market/exchange.GetRate exchange.GetRate}

exchange.IO

exchange.IO()函数用于交易所对象相关的协议、其它接口的调用。

exchange.IO()函数调用交易所对象相关的其它接口,调用成功时返回请求的应答数据,调用失败时返回空值。 string、number、bool、object、array、空值等系统支持的任意类型

exchange.IO(k, …args)

k参数用于设置调用类型,可选值为"api"wait。 k true string 扩展参数,根据具体调用场景传参,arg参数可以传多个。 由于exchange.IO()函数的多态机制,不同的参数设置对应不同的功能。 exchange.IO()函数的参数个数、类型都是不确定的。 arg true string、number、bool、object、array、空值等系统支持的任意类型

function main() {
    while (!exchange.IO("status")) {
        LogStatus("正在等待与交易服务器连接, " + new Date())
    }
}
def main():
    while not exchange.IO("status"):
        LogStatus("正在等待与交易服务器连接, " + _D())
void main() {
    while(exchange.IO("status") == 0) {
        LogStatus("正在等待与交易服务器连接, " + _D());
    }
}

使用status参数,判断与期货公司前置机连接状态: exchange.IO("status"),返回true证明与CTP服务器行情与数据的两台服务器都连接正常。

function on_tick(symbol, ticker) {
    Log("symbol:", symbol, "update")
    Log("ticker:", ticker)
}

function on_order(order) {
    Log("order update", order)
}

function main() {
    while(!exchange.IO("status")) {
        Sleep(10)
    }
    // 如果在程序中不使用诸如exchange.GetTicker()之类的获取行情的函数,可以不设置exchange.IO("mode", 0)
    exchange.IO("mode", 0)
    _C(exchange.SetContractType, "MA005")
    while(true) {
        var e = exchange.IO("wait")
        if(e) {
            if(e.Event == "tick") {
                on_tick(e.Symbol, e.Ticker)
            } else if(e.Event == "order") {
                on_order(e.Order)
            }
        }
    }
}
def on_tick(symbol, ticker):
    Log("symbol:", symbol, "update")
    # 数据结构:https://www.youquant.com/api#ticker
    Log("ticker:", ticker)              

def on_order(order):
    Log("order update", order)

def main():
    # wait connect trade server
    while not exchange.IO("status"):
        Sleep(10)
    # switch push mode
    exchange.IO("mode", 0)
    # subscribe instrument
    _C(exchange.SetContractType, "MA001")
    while True:
        e = exchange.IO("wait")
        if e:
            if e.Event == "tick":
                on_tick(e['Symbol'], e['Ticker'])
            elif e.Event == "order":
                on_order(e['Order'])
void on_tick(const string &symbol, json &ticker) {
    Log("symbol:", symbol, "update");
    Log("ticker:", ticker);
}

void on_order(json &order) {
    Log("order update", order);
}

void main() {
    while(exchange.IO("status") == 0) {
        Sleep(10);
    }
    exchange.IO("mode", 0);
    _C(exchange.SetContractType, "rb2005");
    while(true) {
        auto e = exchange.IO("wait");
        if(e != false) {
            if(e["Event"] == "tick") {
                on_tick(e["Symbol"], e["Ticker"]);
            }   
            else if(e["Event"] == "order") {
                on_order(e["Order"]);
            }
        }
    }
}

使用wait参数设置阻塞: exchange.IO("wait", Timeout),当前交易所有任何品种更新行情信息或订单成交时才返回,可带第二个参数(毫秒数)指定超时,超时返回空值,正常返回EventTick/OrderEvent结构,结合exchange.IO("mode", 0)函数使用,这样配合使用就可以使程序在有最新行情时进行响应,执行程序逻辑(使用exchange.IO("mode", 0)并不影响exchange.IO("wait"),目的是为了在程序中使用exchange.GetTicker()等函数调用时不阻塞)。如果Timeout参数设置-1该函数设置为立即返回,在没有新事件时返回空值,Timeout参数设置0为阻塞等待最新事件,如同不设置Timeout参数。需要注意的是在使用exchange.IO("wait")时,必须至少已经订阅了一个当前处于交易状态的合约(已经交割的过期合约,不会再有行情数据),否则会阻塞在该函数(由于没有任何行情、订单更新)。只支持商品期货实盘。

EventTick{Event:"tick", Index:交易所索引, Nano:事件纳秒级时间, Symbol:合约名称, Ticker:行情数据}OrderTick{Event:"order", Index:交易所索引, Nano:事件纳秒级时间, Order:订单信息}

简单实现回调机制:

function on_tick(symbol, ticker) {
    Log("symbol:", symbol, "update", "ticker:", ticker)
}  

function main() {
    while(!exchange.IO("status")) {
        Sleep(10)
    }
    
    _C(exchange.SetContractType, "MA101")
    _C(exchange.SetContractType, "rb2101")
    _C(exchange.SetContractType, "i2101")
    while(true) {
        var e = exchange.IO("wait", -1)
        if(e) {
            if(e.Event == "tick") {
                on_tick(e.Symbol, e.Ticker)
            }
        }
        Sleep(10)
    }
}
def on_tick(symbol, ticker):
    Log("symbol:", symbol, "update", "ticker:", ticker)  

def main():
    while not exchange.IO("status"):
        Sleep(10)
    _C(exchange.SetContractType, "MA101")
    _C(exchange.SetContractType, "rb2101")
    _C(exchange.SetContractType, "i2101")
    while True:
        e = exchange.IO("wait", -1)
        if e:
            if e.Event == "tick":
                on_tick(e['Symbol'], e['Ticker'])
        Sleep(10)
void on_tick(const string &symbol, json &ticker) {
    Log("symbol:", symbol, "update", "ticker:", ticker);
}

void main() {
    while(exchange.IO("status") == 0) {
        Sleep(10);
    }
    _C(exchange.SetContractType, "MA101");
    _C(exchange.SetContractType, "rb2101");
    _C(exchange.SetContractType, "i2101");
    while(true) {
        auto e = exchange.IO("wait", -1);
        if(e != false) {
            if(e["Event"] == "tick") {
                on_tick(e["Symbol"], e["Ticker"]);
            }
        }
    }
}

多品种回调例子:

function main() {
    while (!exchange.IO("status")) {
        LogStatus("正在等待与交易服务器连接, " + new Date())
    }

    Log("开始获取所有合约")
    var instruments = _C(exchange.IO, "instruments")
    Log("合约列表获取成功")
    var len = 0
    for (var instrumentId in instruments) {
        len++
    }
    Log("合约列表长度为:",len)
}
def main():
    while not exchange.IO("status"):
        LogStatus("正在等待与交易服务器连接, " + _D())
    
    Log("开始获取所有合约")
    instruments = _C(exchange.IO, "instruments")
    Log("合约列表获取成功")
    length = 0
    for i in range(len(instruments)):
        length += 1
    Log("合约列表长度为:", length)
void main() {
    while(exchange.IO("status") == 0) {
        LogStatus("正在等待与交易服务器连接, " + _D());
    }

    Log("开始获取所有合约");
    auto instruments = _C(exchange.IO, "instruments");
    Log("合约列表获取成功");
    int length = 0;
    for(int i = 0; i < instruments.size(); i++) {
        length++;
    }
    Log("合约列表长度为:", length);
}

使用instruments参数,获取所有合约的列表数据: exchange.IO("instruments"),返回交易所所有合约的列表,只支持实盘。 使用products参数,获取所有产品的列表数据:

exchange.IO("products"),返回交易所所有产品的列表,只支持实盘。

使用subscribed参数,获取已经订阅的合约数据:

exchange.IO("subscribed"),返回已订阅行情的合约,只支持实盘。

使用settlement参数,获取结算单数据:

exchange.IO("settlement"),结算单查询,不加第二个参数默认返回之前一个交易日的数据,加参数如20170317指返回日期为2017-03-17的结算单,只支持实盘。

使用api参数,调用底层接口: 优宽量化的CTP(商品期货)终端提供了完整的全API实现,当发明者平台的API满足不了你需要的功能时可以用exchange.IO函数进行更深层的系统调用,完全兼容官方的Api名称。CTP的IO直接扩展函数调用请求,将会在收到第一个isLast标记为true的响应包后返回。

CTP协议接口:CTP协议接口相关资料

以几个简单的例子做为说明:

function main() {
    while (!exchange.IO("status")) {
        LogStatus("正在等待与交易服务器连接, " + new Date())
    }

    Log(exchange.IO("api", "ReqQryInvestor"))
}
def main():
    while not exchange.IO("status"):
        LogStatus("正在等待与交易服务器连接, " + _D())

    Log(exchange.IO("api", "ReqQryInvestor"))
void main() {
    while(exchange.IO("status") == 0) {
        LogStatus("正在等待与交易服务器连接, " + _D());
    }

    Log(exchange.IO("api", "ReqQryInvestor"));
}

查询投资者信息:

function main() {
    // CTP协议建立连接时需要时间
    Sleep(6000)
    exchange.IO("api", "ReqUserPasswordUpdate", {BrokerID: "9999", UserID: "11111", OldPassword: "oldpass", NewPassword: "newpass"})
}
def main():
    Sleep(6000)
    exchange.IO("api", "ReqUserPasswordUpdate", {"BrokerID": "9999", "UserID": "11111", "OldPassword": "oldpass", "NewPassword": "newpass"})
void main() {
    Sleep(6000);
    exchange.IO("api", "ReqUserPasswordUpdate", R"({"BrokerID": "9999", "UserID": "11111", "OldPassword": "oldpass", "NewPassword": "newpass"})"_json);
}

修改密码:

function main() {
    // CTP协议建立连接时需要时间
    Sleep(6000)
    // 如果再加一个参数值为false表示不等待返回值,只发送请求,第三个参数只需要填充需要的字段,也可省略此参数,如果类型为char,传长度为1的字符串即可
    var r = exchange.IO("api", "ReqQryProduct", {ProductID: "MA"})
    // CTP未登陆的时候会失败
    if (!r) {                                                        
        return
    }
    _.each(r, function(item) {
        // IO请求可能返回多个数据包,所以以数组的形式返回。便历数据包的所有数据类型,一个数据包可能包含多个具体数据,具体数据类型的名称,请参看CTP官方文档http://www.sfit.com.cn/5_2_DocumentDown.htm
        _.each(item, function(f) {                                           
            // 取出来需要的数据,Name为此数据的类型,Value为此数据的值
            if (f.Name == 'CThostFtdcProductField') {                
                // 打印查询的的甲醇的信息
                Log(f.Value)                                         
            }
        })
    });
}
def main():
    Sleep(6000)
    r = exchange.IO("api", "ReqQryProduct", {"ProductID": "MA"})
    if not r:
        return

    for r_index in range(len(r)):
        for f_index in range(len(r[r_index])):
            if r[r_index][f_index]["Name"] == 'CThostFtdcProductField':
                Log(r[r_index][f_index]["Value"])
void main() {
    Sleep(6000);
    auto r = exchange.IO("api", "ReqQryProduct", R"({"ProductID": "MA"})"_json);
    if(r == false) {
        return;
    }

    for(auto& ele1 : r.items()) {
        for(auto& ele2 : ele1.value().items()) {
            if(ele2.value()["Name"] == "CThostFtdcProductField") {
                Log(ele2.value()["Value"]);
            }
        }
    }
}

复杂的例子:

function main() {
    while (!exchange.IO("status")) {
        LogStatus("正在等待与交易服务器连接, " + new Date())
    }
    // 也可不指定日期
    var r = exchange.IO("api", "ReqQrySettlementInfo", {TradingDay: "20190506"})    
    var s = ''
    _.each(r, function(item) {
        _.each(item, function(f) {
            if (f.Name == 'CThostFtdcSettlementInfoField') {
                s += f.Value.Content
            }
        })
    })
    Log(s)
}
def main():
    while not exchange.IO("status"):
        LogStatus("正在等待与交易服务器连接, " + _D())
    r = exchange.IO("api", "ReqQrySettlementInfo", {"TradingDay": "20190506"})
    s = ''
    for i in range(len(r)):
        for ii in range(len(r[i])):
            if r[i][ii]["Name"] == "CThostFtdcSettlementInfoField":
                s += r[i][ii]["Value"]["Content"]
    
    Log(s)
void main() {
    while(exchange.IO("status") == 0) {
        LogStatus("正在等待与交易服务器连接, " + _D());
    }
    auto r = exchange.IO("api", "ReqQrySettlementInfo", R"({"TradingDay": "20200311"})"_json);
    string s = "";
    for(auto& ele1 : r.items()) {
        for(auto& ele2 : ele1.value().items()) {
            if(ele2.value()["Name"] == "CThostFtdcSettlementInfoField") {
                s += std::string(ele2.value()["Value"]["Content"]);
            }
        }
    }
    Log(s);
}

复杂的例子:

使用mode参数,切换行情模式:

  • exchange.IO("mode", 0) 立即返回模式,如果当前还没有接收到交易所最新的行情数据推送,就立即返回旧的行情数据,如果有新的数据就返回新的数据。 商品期货中的应用,可以参考:exchange.IO函数的wait参数的使用例子。

  • exchange.IO("mode", 1) 缓存模式(默认模式),如果当前还没有收到交易所最新的行情数据(同上一次接口获取的数据比较),就等待接收然后再返回,如果调用该函数之前收到了最新的行情数据,就立即返回最新的数据。

  • exchange.IO("mode", 2) 强制更新模式,进入等待一直到接收到交易所下一次的最新推送数据后返回。

{@var EXCHANGE_OP_IO_CONTROL}

exchange.Log

exchange.Log()函数用于在日志栏区域输出下单、撤单日志。调用时不会下单,只输出、记录交易日志。

exchange.Log(orderType, price, amount) exchange.Log(orderType, price, amount, …args)

orderType参数用于设置输出的日志类型,可选值为{@var/LOG_TYPE/LOG_TYPE_BUY LOG_TYPE_BUY},{@var/LOG_TYPE/LOG_TYPE_SELL LOG_TYPE_SELL},{@var/LOG_TYPE/LOG_TYPE_CANCEL LOG_TYPE_CANCEL}。 orderType true number price参数用于设置输出的日志中显示的价格。 price true number amount参数用于设置输出的日志中显示的下单量。 amount true number 扩展参数,可以输出附带信息到这条日志中,arg参数可以传多个。 arg false string、number、bool、object、array、空值等系统支持的任意类型

var id = 123
function main() {
    // 下单类型买入,价格999,数量 0.1
    exchange.Log(LOG_TYPE_BUY, 999, 0.1)      
    // 取消订单
    exchange.Log(LOG_TYPE_CANCEL, id)         
}
id = 123
def main():
    exchange.Log(LOG_TYPE_BUY, 999, 0.1)
    exchange.Log(LOG_TYPE_CANCEL, id)
void main() {
    auto id = 123;
    exchange.Log(LOG_TYPE_BUY, 999, 0.1);
    exchange.Log(LOG_TYPE_CANCEL, id);
}

使用exchange.Log(orderType, price, amount)可以进行实盘跟单测试、模拟下单、可以辅助记录下单。

orderType参数为LOG_TYPE_CANCEL时,price参数为撤单的订单Id,用于直接使用exchange.IO()函数撤单时打印撤单日志。 exchange.Log()函数是{@var/EXCHANGE exchange}交易所对象的成员函数,区别于全局函数{@fun/Log Log}。

{@fun/Log Log}, {@var/EXCHANGE exchange}, {@var/LOG_TYPE/LOG_TYPE_BUY LOG_TYPE_BUY}, {@var/LOG_TYPE/LOG_TYPE_SELL LOG_TYPE_SELL}, {@var/LOG_TYPE/LOG_TYPE_CANCEL LOG_TYPE_CANCEL}

Market Account