保持敬畏之心
交易是一场持久战

Pine Script(226):获取未平仓订单的ID与入场时间

#Pine Script入门教学

获取未平仓订单的ID标识符

当一个策略持有仓位时,我们可以使用 strategy.opentrades.entry_id() 函数来获取某一个特定开仓订单的订单ID。这个ID就是我们在开仓时为该笔交易设定的名称。

获取到这个订单ID后,我们可以实现多种功能,例如:通过标签或表格在图表上显示订单的ID;使用这个ID来生成一个特定的平仓指令,以平掉某一笔开仓订单(可以通过 strategy.exit()strategy.close() 函数实现);遍历所有开仓订单,并只处理那些具有特定名称的订单,比如单独计算所有名为”Enter Long”的订单的总利润或总数量;或者根据订单ID将所有开仓订单分组,分别报告它们各自的浮动盈利和回撤。

默认语法结构

该函数的标准语法如下:

strategy.opentrades.entry_id(trade_num)

trade_num 是一个整数,用于指定你想查询哪一笔开仓订单的ID。这个订单编号采用从零开始的索引方式:第一笔开仓订单的编号是0,第二笔是1,第三笔是2,以此类推。要获取最后一笔(即最新一笔)开仓订单的编号,我们可以使用 strategy.opentrades - 1

这个函数的返回值有两种可能:一是返回一个字符串,即指定开仓订单的ID;二是返回 na 值,这在传入的订单编号 trade_num 不正确(例如小于0,或大于等于当前开仓订单的总数 strategy.opentrades),或者策略当前没有任何持仓时会发生。

快速示例

要获取第一笔开仓订单(即最早的那一笔)的ID,我们可以这样做:

// 获取第一笔入场订单的ID
firstOrderID = strategy.opentrades.entry_id(0)

要获取最后一笔开仓订单(即最新的一笔)的ID,可以这样使用:

// 获取最新一笔入场订单的ID
lastOrderID = strategy.opentrades.entry_id(strategy.opentrades - 1)

我们也可以处理所有开仓订单的ID,这需要通过 for 循环来遍历它们。例如,假设我们想在图表上显示所有开仓订单的ID。我们可以创建一个循环,将每个订单的ID拼接成一个字符串,然后在图表上用一个标签显示出来。代码示例如下:

// 遍历所有开仓订单,并将它们的ID拼接成一个字符串
orderIds = ""
for tradeNumber = 0 to strategy.opentrades - 1
    // 如果不是最后一个ID,则在后面加上逗号和空格
    strSuffix = tradeNumber == strategy.opentrades - 1 ? "" : ", "
    orderIds += strategy.opentrades.entry_id(tradeNumber) + strSuffix

// 在图表上显示拼接后的结果
label.new(bar_index, high, orderIds)

函数的特性

strategy.opentrades.entry_id() 返回的订单ID,就是我们之前通过 strategy.entry()strategy.order() 函数在开仓时设定的那个名称。此函数只返回已成交、且当前仍持有的订单的ID,我们无法通过它获取尚未成交的挂单的ID。

这个函数是自PineScript版本5起才可用的新功能,在版本4及更早的版本中不存在。此外,它只能在策略(strategy)脚本中使用。如果在指标(indicator)代码中调用它,PineScript会报错:'You cannot use strategy functions (strategy.opentrades.entry_id) in indicator script.'

示例策略

让我们通过一个完整的策略来看看如何使用 strategy.opentrades.entry_id() 函数。下方的脚本基于一个平滑处理后的EMA进行交易。当价格连续两根K线收于均线之上或之下时,我们开立多仓或空仓。

每当有新的入场交易发生时,我们便使用 strategy.opentrades.entry_id() 来获取该笔交易的ID。然后,我们根据ID的名称(多头或空头),在图表上用不同颜色的标签来显示这个ID。

策略的完整代码如下:

//@version=5
strategy(title="获取开仓交易的入场ID", overlay=true)

// 计算并绘制平滑EMA
smoothEMA = ta.ema(ta.ema(close, 20), 5)
plot(smoothEMA, color=color.lime, linewidth=2, title="平滑EMA")

// 当连续两根K线收于均线之上/下时,开多/空仓
if close > smoothEMA and close[1] > smoothEMA[1]
    strategy.entry("Enter Long", strategy.long)
if close < smoothEMA and close[1] < smoothEMA[1]
    strategy.entry("Enter Short", strategy.short)

// 通过总交易数的变化来判断是否有新交易入场
totalTrades = strategy.closedtrades + strategy.opentrades
newEntry = totalTrades > totalTrades[1] and strategy.opentrades > 0

// 当有新交易入场时,创建一个文本标签
if newEntry
    // 生成标签文本,包含第一笔入场的ID和价格
    labelText = strategy.opentrades.entry_id(0) + "\n@ " + 
         str.tostring(strategy.opentrades.entry_price(0))

    // 如果入场订单的ID包含 "Long" 这个词,就创建一个绿色标签
    // 否则,创建一个红色的、指向上方的标签
    if str.contains(strategy.opentrades.entry_id(0), "Long")
        label.new(bar_index, high, color=#D0F0C0, text=labelText)
    else
        label.new(bar_index, low, color=#FDBCB4, text=labelText,
             style=label.style_label_up)

我们首先计算并绘制了一个平滑EMA。入场逻辑是当价格连续两根K线站上或跌破该均线时,分别开立名为”Enter Long”或”Enter Short”的仓位。

接下来,我们通过比较当前K线的总交易数(strategy.closedtrades + strategy.opentrades)与上一根K线的总交易数,来判断是否有新的交易发生。

最后,我们处理订单ID的显示逻辑:

// 当有新交易入场时,创建一个文本标签
if newEntry
    // ...

newEntry 条件为真时,我们执行两个操作。第一步是生成标签文本:我们将第一笔开仓订单(编号0)的ID和价格拼接成一个字符串,分别使用 strategy.opentrades.entry_id(0)strategy.opentrades.entry_price(0) 来获取这两个信息。第二步是根据ID创建不同颜色的标签:我们使用 str.contains() 函数来检查第一笔订单的ID是否包含”Long”这个词。如果包含,我们就创建一个绿色的标签,显示在K线的最高价处;如果不包含(即为空头订单),我们就创建一个红色的、指向上方的标签,显示在K线的最低价处。

根据策略第一笔开仓订单的ID,脚本会在图表上创建绿色或红色的标签。效果如下:

简单总结一下:strategy.opentrades.entry_id() 函数返回某一个特定开仓订单的订单ID(名称)。我们通过一个订单编号来告知函数我们想要查询哪一笔订单。订单编号从0开始,代表第一笔开仓的交易,并以 strategy.opentrades - 1 结束,代表最后一笔(即最新一笔)入场交易。

获取未平仓订单的入场时间

当一个策略持有仓位时,我们可以通过 strategy.opentrades.entry_time() 函数来获取某个特定持仓订单的入场时间。这个函数能告诉我们一个订单是在哪个具体的日期和时间开仓的。

了解一个订单的入场时间在多种场景下都很有用,例如:查看距离仓位中第一笔订单的入场已经过去了多长时间,或者测量自最近一次加仓以来经过了多久;计算连续开仓订单之间的时间间隔;计算所有在数小时前入场的持仓订单的当前盈亏、最大回撤和最大浮盈。

标准语法格式

该函数的标准语法格式如下:

strategy.opentrades.entry_time(trade_num)

trade_num 是持仓订单的编号。这个整数参数告诉PineScript要返回哪个持仓订单的入场时间。这个编号是一个从零开始的索引:策略开立的第一个订单编号为0,第二个为1,第三个为2,以此类推。我们可以通过 strategy.opentrades - 1 来获取最后一个(即最近的)持仓订单的编号。

这个函数的返回值有两种可能:一是一个时间值,代表订单开仓的日期和时间——PineScript中的时间值是以自1970年1月1日00:00:00 UTC以来的毫秒数来表示的;二是一个 na 值,这在提供的订单编号不正确,或者策略当前没有任何持仓交易时会发生。

快速示例

要获取仓位中第一笔(即最早的)订单的入场时间,我们使用订单编号0:

// 获取持仓中第一笔订单的入场时间
firstEntryTime = strategy.opentrades.entry_time(0)

要获取最近一笔订单的入场时间,则可以这样使用:

// 获取最后一笔(即最近的)订单的入场时间
lastEntryTime = strategy.opentrades.entry_time(strategy.opentrades - 1)

另一个常见的应用是遍历所有持仓订单。例如,我们可以计算所有持仓订单的平均入场时间。为此,我们使用一个 for 循环来遍历所有订单,在循环中将每个订单的入场时间累加起来,最后除以订单总数即可:

// 对当前所有持仓交易的入场时间进行求和
entryTimeSum = 0
for tradeNumber = 0 to strategy.opentrades - 1
	entryTimeSum += strategy.opentrades.entry_time(tradeNumber)

// 计算平均入场时间(以自1970年1月1日以来的毫秒数表示)
avgEntryTime = entryTimeSum / strategy.opentrades

返回的是K线时间,而非精确的订单成交时间

关于 strategy.opentrades.entry_time() 的一个重要特性:它返回的并不是订单确切的成交时间,而是订单成交所在那根K线的开盘时间。

这个近似值是否会带来问题,取决于具体情况。如果订单是在K线开盘时成交的,那么该函数给出的入场时间是准确的(因为TradingView的K线时间戳就是基于K线的开盘时间)。而如果订单是在K线内部的某个时间点成交的,那么该函数返回的就不是实际的入场时间,而只是一个估计值。在较长的时间周期上,这种误差会更明显。

总的来说,PineScript通常会高估一个订单的持仓时间。因为即使订单是在K线快收盘时才成交,strategy.opentrades.entry_time() 返回的仍然是这根K线在很久之前开盘的时间。

函数的特性

strategy.opentrades.entry_time() 返回的是毫秒数,这种格式通常不便于我们直接使用。为了使其更实用,我们通常需要将其转换为秒、分钟、小时或天。

另一个容易踩坑的地方是时区:这个函数返回的时间是UTC时区。这一点与PineScript中几乎所有其他处理时间的变量和函数形成对比,后者大多使用交易品种所在交易所的时区。

此外,如果多个订单在同一根K线上成交,它们都会有相同的返回值,即使它们的实际成交时间点不同。这个函数是从PineScript版本5开始才可用的,且不能在指标(Indicator)脚本中使用,否则会报错。

示例策略

让我们看一个使用 strategy.opentrades.entry_time() 函数的完整策略。下面的脚本基于近期高低点的突破进行交易。当策略持仓时,它会每隔10根K线计算一次自第一笔订单入场以来经过了多少分钟,以此来展示仓位的持有时间。

该策略的完整代码如下:

//@version=5
strategy(title="Open trade entry time", overlay=true)

// 计算并绘制近期高低点
highestHigh = ta.highest(high, 20)[1]
lowestLow   = ta.lowest(low, 20)[1]
plot(highestHigh, color=color.green, title="Highest High")
plot(lowestLow, color=color.red, title="Lowest Low")

// 生成突破交易
if high > highestHigh
    strategy.entry("Enter Long", strategy.long, stop=close)
if low < lowestLow
    strategy.entry("Enter Short", strategy.short)

// 当有持仓时,每10根K线显示一次自初始入场以来的分钟数
if strategy.position_size != 0 and bar_index % 10 == 0
    minutesSinceEntry = (time - strategy.opentrades.entry_time(0)) / (60 * 1000)

    label.new(bar_index, high, color=color.black, textcolor=color.white,
         text=str.tostring(minutesSinceEntry) + " 分钟\n持仓时间")

我们首先用 strategy() 函数配置脚本属性。然后计算并绘制20周期的高低点通道。接着,两个 if 语句根据价格是否突破通道来提交开仓订单。

最后,我们报告当前仓位的持有时间:

// 当有持仓时,每10根K线显示一次自初始入场以来的分钟数
if strategy.position_size != 0 and bar_index % 10 == 0
    minutesSinceEntry = (time - strategy.opentrades.entry_time(0)) / (60 * 1000)

    label.new(bar_index, high, color=color.black, textcolor=color.white,
         text=str.tostring(minutesSinceEntry) + " 分钟\n持仓时间")

这个 if 语句检查两个条件:策略是否有持仓(strategy.position_size != 0),以及当前K线的编号是否是10的整数倍(bar_index % 10 == 0)。当两个条件都满足时,代码块执行。

在代码块中,我们首先计算自第一笔订单入场以来经过的分钟数。我们用当前K线的开盘时间(time)减去第一笔订单的入场时间(strategy.opentrades.entry_time(0))。这个结果是毫秒数。为了将其转换为分钟,我们再除以 (60 * 1000)

然后,label.new() 函数创建一个文本标签,在图表上显示这个持仓分钟数。在图表上,策略会每隔10根K线报告一次自初始入场以来的分钟数。效果如下:

简单总结一下:strategy.opentrades.entry_time() 函数返回一个特定持仓订单的入场时间。一个订单编号参数告诉函数要返回哪个订单的数据,第一个订单使用0,最后一个订单使用 strategy.opentrades - 1。该函数返回的时间是一个以毫秒为单位的UTC时间戳,且返回的并不是订单确切的成交时间,而是其成交所在K线的开盘时间。

赞(0)
未经允许不得转载:图道交易 » Pine Script(226):获取未平仓订单的ID与入场时间
分享到

评论 抢沙发

登录

找回密码

注册