本帖最后由 资深技术02 于 2023-9-21 15:54 编辑
二、Order对象 1、基本介绍:Order对象是你在金字塔软件下使用VBA下单和查询订单的对象,其重要程度不言而喻了吧。 2、主要属性:(本帖以CTP平台为主要平台,以下讲到的都是CTP平台使用的) (1)Holding2:得到当前指定帐户的国内期货持仓品种数量 (2)OrderNum2:得到所有国内期货当前有效的未成交合约品种数量 (3)OrderQueue:顺序执行下单成交,即按委托顺序成交报单,可以用于平仓反手,套利等委托动作 3、有用的方法: Account:得到当前默认帐户信息
Account2:得到指定的国内期货帐户信息
Buy:开多操作
Sell:平多操作
BuyShort:开空操作
SellShort:平空操作
CancelOrder:执行撤单操作
HoldingInfo2:取指定索引的指定CTP帐户的合约持仓信息
HoldingInfoByCode2:取指定CTP品种的持仓合约信息
OrderInfoByCode:取指定品种的未成交IB合约信息
OrderInfo2:取指定索引的未成交CTP合约信息
OrderInfoByCode2:取指定品种的未成交CTP合约信息
Contract:取指定品种的合约信息
ChargeByNum:计算指定品种的本次交易手续费用
IsAccount:判断指定帐号是否是当前已登录有效帐号,例如 Order.IsAccount("351579"),如果该账户已登录则返回1,否则返回0 4、事件 OrderStatusEx2:当委托订单出现变化时发生该扩展事件,比如撤单、成交等 应用场景及代码片段: 1、获取指定者账户的所有持仓合约,保存到一个字符串中。 此例需要解决的问题:首先要获取账户的总持仓数,需要用到Holding2属性,然后要逐一循环取出每一个持仓合约的持仓量,需要用到HoldingInfo2方法。 [Visual Basic] 复制代码 function GetHoldStr(sAccount)
dim i
dim BuyHold
dim BuyCost
dim SellHold
dim SellCost
dim CurCode
dim CurMarket
On Error resume Next
HoldStr=""
HoldingCount=Order.Holding2(sAccount)
If HoldingCount>0 then
For i=0 to HoldingCount-1
CallOrder.HoldingInfo2(i,BuyHolding,BuyCost,BuyTodayHolding,SellHolding,SellCost,SellTodayHolding,PNL,UseMargin,Code,Market,sAccount)
CurCode=Code
CurMarket=Market
BuyHold=BuyHolding
SellHold=SellHolding
HoldStr=HoldStr & CurCode
if BuyHold>0 then
HoldStr=HoldStr & ":+" &BuyHold
end if
if SellHold>0 then
HoldStr=HoldStr & ":-" &SellHold
end if
HoldStr=HoldStr & ","
Next
HoldStr=Left(HoldStr,len(HoldStr)-1)
End If
GetHoldStr=HoldStr
End function
本代码使用函数方式,传递一个账户号码,就可以获取该账户的持仓信息,调用方法是:hold=GetHoldStr("88888888")。 2、获取指定合约的信息,包括合约最小跳动单位,合约保证金比例、合约乘数。 [Visual Basic] 复制代码 private iMultipliter,iMinTick,iShortPercent,iLongPercent
SubGetContractHold(sCode,sMarket) '获取合约的信息
'Application.MsgOut sCode & "," &sMarket
on error resume next
CallOrder.Contract(sCode,sMarket,Multipliter,MinTick,ShortPercent,LongPercent)
iMultipliter=Multipliter
'application.MsgOut iMultipliter
iMinTick=MinTick
iShortPercent=ShortPercent
iLongPercent=LongPercent
End Sub
本例使用变量来存储合约信息的4个值,所以,变量定义置于过程顶端,调用本过程之后,变量就存储了该合约的对应值,其他过程就可以直接使用了。 3、获取未成交的订单信息 [Visual Basic] 复制代码
FunctionGetPendingOrder(sCode,sMarket) '获取未成交单
dim Orderid '订单ID
dim Filled '提交手数
dim Remaining '剩余手数
dim Action '买卖
dim OrderType '订单类型
dim LmtPrice '委托价
dim Account '账户
dim Kaiping '开平
GetPendingOrder=0
PendingCount=Order.OrderNum2
For i=0 to PendingCount-1
CallOrder.OrderInfo2(i,OrderID,ConSign,Filled,Remaining,Action,OrderType,LmtPrice,Account,Kaiping,Code,Market)
if Code=sCode then
GetPendingOrder=OrderID
end if
Next
end function
本函数返回指定合约的未成交单的订单号,调用方法:OrdID=GetPendingOrder("IF05","ZJ"),然后根据这个返回的OrdID,你可以进行其他的操作,比如,如果是要下单,先看有没有未成交的委托单,如果有就不下单,或者取消该委托单然后再下单等。
4、取消所有委托单 [Visual Basic] 复制代码 dim Orderid '订单ID
dim Filled '提交手数
dim Remaining '剩余手数
dim Action '买卖
dim OrderType '订单类型
dim LmtPrice '委托价
dim Account '账户
dim Kaiping '开平
PendingCount=Order.OrderNum2
For i=0 to PendingCount-1
CallOrder.OrderInfo2(i,OrderID,ConSign,Filled,Remaining,Action,OrderType,LmtPrice,Account,Kaiping,Code,Market)
CancelOrder OrderID
Next
End Sub
这个过程,遍历每一个委托单,逐一进行撤销操作。如果你要撤销指定OrderID的委托单,只需对此过程稍作修改就可以实现了。 5、获取指定品种的持仓量、持仓均价 [Visual Basic] 复制代码 private AccountID,iBuyHold,iSellHold,BuyPrice,SellPrice
SubGetHoldByCode(sAccount,sCode,sMarket)
dim i,k
dim BuyHolding
dim BuyCost
dim BuyTodayHolding
dim SellHolding
dim SellCost
dim SellTodayHolding
dim PNL
dim UseMargin
dim Code
dim Market
On Error resume Next
AccountStatus=Order.Account2(2,sAccount)
'application.MsgOut sCode & "," &sMarket & "," & sAccount & ",NextCode:" &NextCode & ",账户状态:" & AccountStatus
if AccountStatus=255 OrAccountStatus="" then
exit sub
end if
CallOrder.HoldingInfoByCode2(sCode,sMarket,BuyHolding,BuyCost,BuyTodayHolding,SellHolding,SellCost,SellTodayHolding,PNL,UseMargin,sAccount)
iBuyHold=BuyHolding
iSellHold=SellHolding
BuyPrice=BuyCost
SellPrice=SellCost
End Sub
这个过程也是将返回的值保存到外部变量,供其他过程使用。所以过程前的定义变量必不可少。 使用方式:GetHoldByCode"8888888","IF05","ZJ" '传入交易账户、合约代码、市场代码 6、下单指令封装成过程:
Order对象的下单指令buy,sell,buyshort,sellshort,每次要使用都得看参数怎么用的,是不是很不方便呢?我把他们写成4个过程了,看看是不是很好? 参数说明: nPrice传入的价格,传入0就是市价委托,否则就是限价委托,sCode合约代码,sMarket市场代阿玛,iOrdID委托量,sAccount交易的账户 这下,你再也不用多次翻看帮助了,只要记住这4个过程的名字就行了。 [Visual Basic] 复制代码 '开多单
Sub KaiDuoDan(nPrice,sCode,sMarket,iOrdVol,sAccount) '开多单,nPrice=0时为市价,否则就是传递过来的价
'application.MsgOut "iOrdVol:" & iOrdVol &"," & sCode & "," & sMarket & ","& sAccount & "," & nPrice
If iOrdVol>0 then
If nPrice=0 then
'application.MsgOut "sCode,sMarket,AccountID:"& sCode & "," & sMarket & "," & AccountID
CallOrder.Buy(1,iOrdVol,0,0,sCode,sMarket,sAccount,0) '市价开多单
Else
CallOrder.Buy(0,iOrdVol,nPrice,0,sCode,sMarket,sAccount,0) '限价开多单
End If
End If
End Sub
'开空单
Sub KaiKongDan(nPrice,sCode,sMarket,iOrdVol,sAccount) '开空单,nPrice=0时为市价,否则就是传递过来的价
'application.MsgOut "iOrdVol:" & iOrdVol &"," & sCode & "," & sMarket & ","& sAccount & "," & nPrice
If iOrdVol>0 then
If nPrice=0 then
Call Order.BuyShort(1,iOrdVol,0,0,sCode,sMarket,sAccount,0) '市价开空单
Else
CallOrder.BuyShort(0,iOrdVol,nPrice,0,sCode,sMarket,sAccount,0) '限价开空单
End If
End If
End Sub
'平多单
Sub PingDuoDan(nPrice,sCode,sMarket,iOrdVol,sAccount) '平多单,nPrice=0时为市价,否则就是传递过来的价
If iOrdVol>0 then
If nPrice=0 then
CallOrder.Sell(1,iOrdVol,0,0,sCode,sMarket,sAccount,0) '市价平多单
Else
CallOrder.Sell(0,iOrdVol,nPrice,0,sCode,sMarket,sAccount,0) '限价平多单
End If
End If
End Sub
'平空单
Sub PingKongDan(nPrice,sCode,sMarket,iOrdVol,sAccount) '平空单,nPrice=0时为市价,否则就是传递过来的价
If iOrdVol>0 then
If nPrice=0 then
CallOrder.SellShort(1,iOrdVol,0,0,sCode,sMarket,sAccount,0) '市价平空单
Else
CallOrder.SellShort(0,iOrdVol,nPrice,0,sCode,sMarket,sAccount,0) '限价平空单
End If
End If
End Sub
7、计算订单手续费 手续费的计算可以使用ChargeByNum(Code,Market, lmtPrice, Volume, Type)方法 如计算股指期货IF05的交易手续费,可以这么做: sxf=ChargeByNum("IF05","ZJ",2650,2,0) 参数说明:Code合约代码、Market市场代码、lmtPrice委托价、Volume委托量、Type买卖方向
使用此方法计算的手续费取决于你是否正确设置了合约信息中的保证金比例、手续费标准,如果设置不对,计算就不对了。 8、根据合约代码获取持仓量、持仓均价并存入全局变量中共后台策略调用 [Visual Basic] 复制代码
'传入交易账户号、合约代码、市场代码 如:GetHoldByCode"88888888","IF05","ZJ"
SubGetHoldByCode(sAccount,sCode,sMarket)
dimi
dim BuyHolding
dim BuyCost
dim BuyTodayHolding
dim SellHolding
dim SellCost
dim SellTodayHolding
dim PNL
dim UseMargin
dim Code
dim Market
On Error resume Next
AccountStatus=Order.Account2(2,sAccount) '检测账户是否登陆,如果没有登陆就退出
'application.MsgOut sCode & "," & sMarket &"," & sAccount & ",NextCode:" & NextCode &",账户状态:"& AccountStatus
if AccountStatus=255 Or AccountStatus="" then
exit sub
end if
CallOrder.HoldingInfoByCode2(sCode,sMarket,BuyHolding,BuyCost,BuyTodayHolding,SellHolding,SellCost,SellTodayHolding,PNL,UseMargin,sAccount)
iBuyHold=BuyHolding
iSellHold=SellHolding
DuoPrice=BuyCost
KongPrice=SellCost
Call Document.SetExtData("多开仓价",DuoPrice)
Call Document.SetExtData("空开仓价",KongPrice)
Call Document.SetExtData("多持仓",iBuyHold)
Call Document.SetExtData("空持仓",iSellHold)
EndSub
图表或后台策略中调用全局变量的方法: aa:=extgbdata('多开仓价'); bb:=extgbdata('空开仓价'); cc:=extgbdata('多持仓); dd:=extgbdata('空持仓);
9、OrderStatusEx2事件
Order对象的OrderStatusEx和OrderStatusEx2的区别是,后者返回了交易账户。我个人更喜欢使用后者,可以精确指定对那个帐户的交易情况进行处理。
从帮助文字可以看出,这个事件监控订单的变化情况,从下单、撤单、成交等都可以实时回传给你的,通过这个事件,你可以做很多事件的。 (1)做一个账户跟踪程序,跟踪另一个账户的交易,就要用到这个事件,具体思路是有成交时,判断是哪一个账户成交,如果是你要监控的账户,就同步在另一个账户开同向的仓位。 这个实例等我闲下来整理一下代码,可以奉献给大家,敬请期待。 (2)可以做一个将成交记录实时写到Excel的程序,这样你就可以清楚地看到你当前的交易,盈亏计算也可以在excel中完成。 (3)用在套利策略中,可以用来处理单腿交易等。 (4)其他需要监控账户变动情况,如:下单后多长时间不成交撤单,你需要记录下单的时间,然后比较最新时间与该时间的间隔来确定是否需要撤单。
需要说明一下金字塔返回的订单状态: 1)Submitted:是已经提交订单。 2)Filled:是已经成交的订单。 3)Tradeing:是成交回报,可能filled状态的单成交时分多次成交,那么这个状态的单就会有多个。 4)Cancelled:是已经取消的单
下面是一个将成交情况存入全局变量的实例
[Visual Basic] 复制代码 Sub ORDER_OrderStatusEx2(OrderID,Status, Filled, Remaining, Price, Code, Market, OrderType, Aspect,Kaiping,Account, AccountType)
'账户类型 0 IB 1 CTP 2 金仕达
Dim sStatus '成交状态
If AccountType=0 then
sAccType="0.IB"
ElseIf AccountType=1 then
sAccType="1.CTP"
ElseIf AccountType=2 then
sAccType="2.金士达"
End if
If AccountType=0 then
sStatus="FILLED"
ElseIf AccountType=1 then
sStatus="TRADEING"
ElseIf AccountType=2 then
sStatus="FILLED"
End if
If UCase(Status)="FILLED" then '只跟踪成交的单
if Aspect=0 and Kaiping=0 then '买入
CallDocument.SetExtString("Order-Buy-time",time) '成交时间
CallDocument.SetExtData("Order-B-Price",Price) '成交价格
CallDocument.SetExtData("Order-B-Vol",Filled) '成交手数
Call Document.SetExtData("Order-B-OrderID",OrderID) '成交单号
end if
if Aspect=1 and Kaiping=0 then '卖出
Call Document.SetExtString("Order-S-time",time) '成交时间
CallDocument.SetExtData("Order-S-Price",Price) '成交价格
CallDocument.SetExtData("Order-S-Vol",Filled) '成交手数
CallDocument.SetExtData("Order-S-OrderID",OrderID) '成交单号
end if
if Aspect=1 and Kaiping>0 then '卖平
CallDocument.SetExtString("Order-Sp-time",time) '成交时间
CallDocument.SetExtData("Order-Sp-Price",Price) '成交价格
Call Document.SetExtData("Order-Sp-Vol",Filled) '成交手数
CallDocument.SetExtData("Order-Sp-OrderID",OrderID) '成交单号
end if
if Aspect=0 and Kaiping>0 then '买平
CallDocument.SetExtString("Order-Bp-time",time) '成交时间
CallDocument.SetExtData("Order-Bp-Price",Price) '成交价格
CallDocument.SetExtData("Order-Bp-Vol",Filled) '成交手数
end if
End if
End Sub
把这段代码复制到你的金字塔vba模块中,试着下几个单,然后可以看看全局变量中是否有下单时间、成交价格、成交手数、成交单号这些变量。
|