订单的基本就五个功能:
SendInstantOrder - 发送即时市价买卖订单
SendPendingOrder - 发送挂单(如限价买入,止损买入,限价卖出,止损卖出)
ModifyOrder - 修改订单,如更改止损/止赢,或未完成订单的价格。7
CloseOrder - 关闭订单
DeleteOrder - 删除已挂起的订单
继续使用上一节的代码演示订单功能,每天早上8点发送即时市价单:
a.先将策略名更新
StrategyShortName('8点开仓'); //策略名
StrategyDescription('每天8点开仓'); //策略简短描述
b.在外部定义一个参数- Currency,以确认哪个交易标的使用此策略:
var
Currency: PChar;
...
RegOption('Currency', ot_Currency, Currency);
c.我们将在 GetSingleTick 过程中添加以下几行。 在GetSingleTick里会收到了所有的价格变化。
procedure GetSingleTick; stdcall;
var
time: TDateTime;
OrderHandle: Integer;
begin
//检查是否是我们交易的标的。Symbol是一个函数,它返回当前标的(货币)的名称。
//如果它不是设定的标的,就退出GetSingleTick,什么也不做。
if symbol <> Currrency then
exit;
//获取当前时间作为标的最后 1 分钟时间。
time:= iTime(Symbol, PERIOD_M1,0);
//使用 HourOf(time) 函数检查当前时间是否为上午 8 点
//(该函数和其他处理时间的函数位于 DateUtils 模块中,我们将其添加到“uses”声明中)
// 以及未平仓和未完成的订单为0时下单
if (HourOf(time) = 8) and (OrdersTotal = 0) then
SendInstantOrder(Symbol, op_Buy, 0.1, Ask - 100*Point, Ask + 50*Point, '', 0, OrderHandle);
完整的代码如下:
library DemoStrategy;
uses
SysUtils, StrategyInterfaceUnit, TechnicalFunctions,DateUtils;
// 外部参数
var
Delta: double = 3.46;
StopLoss: integer = 20;
Day: longword = 7;
UseStopLoss: boolean = true;
List: Integer = 0;
Currency: PChar;
SomeInfo: PChar;
procedure InitStrategy; stdcall;
begin
StrategyShortName('8点开仓'); //策略名
StrategyDescription('每天8点开仓'); //策略简短描述
RegOption('Delta', ot_Double, Delta); // 创建参数(名称,类型,选项)
RegOption('止损', ot_Integer, StopLoss); // 创建参数(名称,类型,选项)
RegOption('天数', ot_Longword, Day); // 创建参数(名称,类型,选项)
RegOption('是否', ot_Boolean, UseStopLoss); // 创建参数(名称,类型,选项)
AddSeparator('分隔符');
RegOption('列表', ot_EnumType, List);
AddOptionValue('列表', '选项1');
AddOptionValue('列表', '选项2');
AddOptionValue('列表', '选项3');
RegOption('Currency', ot_Currency, Currency);
ReplaceStr(Currency,'EURUSD');
RegOption('SomeInfo', ot_String, SomeInfo);
ReplaceStr(SomeInfo, 'Information for user');
SetOptionRange('Delta', 0, 100); //定义参数范围0-100
SetOptionDigits('Delta', 2); //参数小数点后最多2位
end;
procedure DoneStrategy; stdcall;
begin
end;
procedure ResetStrategy; stdcall;
begin
end;
procedure GetSingleTick; stdcall;
var
time: TDateTime;
OrderHandle: Integer;
begin
//检查是否是我们交易的标的。Symbol是一个函数,它返回当前标的(货币)的名称。
//如果它不是设定的标的,就退出GetSingleTick,什么也不做。
if symbol <> Currency then
exit;
//获取当前时间作为标的最后 1 分钟时间。
time:= iTime(Symbol, PERIOD_M1,0);
//使用 HourOf(time) 函数检查当前时间是否为上午 8 点
//(该函数和其他处理时间的函数位于 DateUtils 模块中,我们将其添加到“uses”声明中)
// 以及未平仓和未完成的订单为0时下单
if (HourOf(time) = 8) and (OrdersTotal = 0) then
SendInstantOrder(Symbol, op_Buy, 0.1, Ask - 100*Point, Ask + 50*Point, '', 0, OrderHandle);
end;
exports
InitStrategy,
DoneStrategy,
ResetStrategy,
GetSingleTick;
end.
编译之后,将其加载到策略列表中,表现如下:
关于SendInstantOrder参数,它接收下列信息:
Symbol - 开仓标的名称
OperationType - 开仓类型 op_Buy or op_Sell
LotSize - 仓位大小 (0.1)
StopLoss - 止损,例子中计算为Ask - 100*Point(Point 是该货币的最小点值(0.0001))
TakeProfit - 止盈,例子中计算为Ask + 50*Point
Comment - 为该订单添加文本注释,也可以将其留空
MagicNumber - 必要时用于将一组订单与另一组订单分开
如果此函数执行成功,它将返回“true”值和OrderHandle值(唯一的订单标识符,您可以稍后使用它来修改、关闭或删除该订单)。
在参数对话框中自定义头寸大小,止损/止赢和开始下单时间
调整后的代码如下:
library hour;
uses
SysUtils, StrategyInterfaceUnit, TechnicalFunctions,DateUtils;
// 外部参数
var
TakeProfit: integer = 1000;
StopLoss: integer = 500;
OpenTime: integer = 7;
Currency: PChar;
Lot: double = 0.1;
procedure InitStrategy; stdcall;
begin
StrategyShortName('8点开仓'); //策略名
StrategyDescription('每天8点开仓'); //策略简短描述
RegOption('止赢', ot_Integer, TakeProfit); // 止赢
RegOption('止损', ot_Integer, StopLoss); // 止损
RegOption('下单时间', ot_Integer, OpenTime); // 下单时间
RegOption('手数', ot_Double, Lot); // 止赢
AddSeparator('分隔符');
RegOption('下单标的', ot_Currency, Currency);
ReplaceStr(Currency,'EURUSD');
end;
procedure DoneStrategy; stdcall;
begin
end;
procedure ResetStrategy; stdcall;
begin
end;
procedure GetSingleTick; stdcall;
var
time: TDateTime;
OrderHandle: Integer;
begin
//检查是否是我们交易的标的。Symbol是一个函数,它返回当前标的(货币)的名称。
//如果它不是设定的标的,就退出GetSingleTick,什么也不做。
//if symbol <> Currency then
// exit;
//获取当前时间作为标的最后 1 分钟时间。
time:= iTime(Symbol, PERIOD_M1,0);
//使用 HourOf(time) 函数检查当前时间是否为上午 8 点
//(该函数和其他处理时间的函数位于 DateUtils 模块中,我们将其添加到“uses”声明中)
// 以及未平仓和未完成的订单为0时下单
if (HourOf(time) = OpenTime) and (OrdersTotal = 0) then
SendInstantOrder(Symbol, op_Buy, Lot, Ask - StopLoss*Point, Ask + TakeProfit*Point, '', 0, OrderHandle);
end;
exports
InitStrategy,
DoneStrategy,
ResetStrategy,
GetSingleTick;
end.
挂单(SendPendingOrder)的使用
挂单(SendPendingOrder)与市价单(SengInstantOrder)非常相似,它使用一个额外的参数ExecutionPrice(如何执行),订单类型可以分4类:
op_BuyLimit - 买入限价 在当前价格下方挂买单(低价买入)
op_BuyStop - 买入止损 在当前价格上方挂买单(高价买入)
op_SellLimit - 卖出限价 在当前价格上面挂卖单 (高价卖出)
op_SellStop - 卖出止损 在当前价格下方挂卖单 (低价卖出)
继续修改上方策略,在早上8点挂单,如果10点没有执行,就删除挂单.
首先,修改8点时市价单(SengInstantOrder)为挂单(SendPendingOrder),价格为ask - 30点,即比现在卖出价低30点.
if (HourOf(time) = OpenTime) and (OrdersTotal = 0) then
SendPendingOrder(Symbol, op_BuyLimit, Lot, Ask - StopLoss*Point, Ask + TakeProfit*Point, Ask - 30*Point'', 0, OrderHandle);
注意: 将OrderHandle 变量从GetSingleTick改为全局变量,即使退出GetSingleTick也会记录这个订单ID,在重启策略(ResetStrategy)时也记录了这个订单ID
然后跟踪这个订单 如果OrderHendle等于 -1 那么什么也不用做:
if OrderHandle <> -1 then ...
从订单列表中选择我们的订单( 如果OrderSelect函数返回 false,则我们假设订单已被止损或止盈关闭。)
if not (OrderSelect(OrderHandle,SELECT_BY_TICKET, MODE_TRADES)) then
begin
OrderHandle:= -1;
exit;
end;
检查订单类型,因为它可能已经被执行,将其类型更改为 tp_Buy 或 tp_Sell。
这种情况下,它不再是挂单。
if OrderType <> tp_BuyLimit then
begin
OrderHandle := -1
exit;
end;
最后一次检查,如果当前时间等于或大于设定的10点,订单没有执行,我们删除它。
// 到10点未成交 处理
if HourOf(time) >= OpenTimeNext then
begin
DeleteOrder(OrderHandle);
OrderHandle := -1;
end;
完整的代码如下:
library hour;
uses
SysUtils, StrategyInterfaceUnit, TechnicalFunctions,DateUtils;
// 外部参数
var
TakeProfit: integer = 1000;
StopLoss: integer = 1000;
OpenPrice: integer = 500;
OpenTime: integer = 8;
OpenTimeNext: integer = 10;
Currency: PChar;
Lot: double = 0.1;
OrderHandle: integer; //将OrderHandle改为全局变量
procedure InitStrategy; stdcall;
begin
StrategyShortName('8点开仓'); //策略名
StrategyDescription('每天8点开仓'); //策略简短描述
RegOption('下单时间', ot_Integer, OpenTime); // 下单时间
RegOption('删单时间', ot_Integer, OpenTimeNext); // 删单时间
AddSeparator('分隔符');
RegOption('下单标的', ot_Currency, Currency);
RegOption('挂多低于现价', ot_Integer, OpenPrice); // 开仓
RegOption('手数', ot_Double, Lot); // 手数
RegOption('止赢', ot_Integer, TakeProfit); // 止赢
RegOption('止损', ot_Integer, StopLoss); // 止损
ReplaceStr(Currency,'EURUSD');
end;
procedure DoneStrategy; stdcall;
begin
FreeMem(Currency);
end;
procedure ResetStrategy; stdcall;
begin
OrderHandle := -1;
end;
procedure GetSingleTick; stdcall;
var
time: TDateTime;
price: double;
begin
//检查是否是我们交易的标的。Symbol是一个函数,它返回当前标的(货币)的名称。
//如果它不是设定的标的,就退出GetSingleTick,什么也不做。
if symbol <> Currency then
exit;
//获取当前时间作为标的最后 1 分钟时间。
time := iTime(Symbol, PERIOD_M1, 0);
//使用 HourOf(time) 函数检查当前时间是否为上午 8 点
//(该函数和其他处理时间的函数位于 DateUtils 模块中,我们将其添加到“uses”声明中)
// 以及未平仓和未完成的订单为0时下单
if (HourOf(time) = OpenTime) and (OrdersTotal = 0) then
begin
price := Ask - OpenPrice*Point;
SendPendingOrder(Symbol, op_BuyLimit, Lot, price - StopLoss*Point, price + TakeProfit*Point, price,'8点动手', 0, OrderHandle);
end;
// 假如已有订单
if OrderHandle <> -1 then
begin
//选择这个订单
if not(OrderSelect(OrderHandle, SELECT_BY_TICKET, MODE_TRADES)) then
begin
OrderHandle:= -1;
exit;
end;
//检查它的类型
if OrderType <> tp_BuyLimit then
begin
OrderHandle := -1;
exit;
end;
// 到10点未成交 处理
if HourOf(time) >= 10 then
begin
DeleteOrder(OrderHandle);
OrderHandle:= -1;
end;
end;
end;
exports
InitStrategy,
DoneStrategy,
ResetStrategy,
GetSingleTick;
end.