Forex Tester 交易策略 - 订单功能的使用

订单的基本就五个功能:

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tmlige

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值