
“该策略通过识别过度反应日来交易澳元/美元,在17:00开仓,方向与当日走势一致,并在日内收盘前平仓,利用显著的日内波动性。”
资产类别: 差价合约、远期、期货、掉期 | 地区: 美国 | 周期: 日内 | 市场: 外汇 | 关键词: 价格
I. 策略概要
该策略侧重于澳元/美元货币对,根据Wong在1997年的方法,当每日回报超过平均回报加上两个标准差(在50天内计算)时,识别过度反应日。当在17:00检测到过度反应日时,以过度反应的方向开仓并在当天结束时平仓。这种方法利用了大幅、异常的价格变动,利用动态触发方法来识别交易机会。该策略简单直接,并对外汇/美元货币对的显著日内市场波动做出反应。
II. 策略合理性
过度反应日的回报与平常日相比存在统计学上的显著差异,累积异常回报全天都在增加,表明策略具有盈利能力。观察到强烈的动量效应,价格持续向过度反应的方向移动,这由行为偏差和心理效应驱动,这些是动量异常的常见驱动因素。过度反应通常在美国交易时段开始时变得明显。该策略利用了市场效率低下,因为基于过度反应异常的盈利交易挑战了有效市场的概念。这种动量驱动的方法突出了该策略在利用金融市场中的心理和行为模式方面的功能基础。
III. 来源论文
Price Overreactions in the Forex and Trading Strategies [点击查看论文]
- 古列尔莫·玛丽亚·卡波拉莱(Guglielmo Maria Caporale)和亚历克斯·普拉斯顿(Alex Plastun),布鲁内尔大学伦敦分校经济与金融系;伦敦南岸大学;CESifo(经济研究中心和IFO研究所);德国经济研究所(DIW Berlin);苏梅国立大学
<摘要>
本文通过使用2008年1月1日至2018年12月31日期间欧元/美元、美元/日元、美元/加元、澳元/美元和欧元/日元汇率的日内和日间数据,探讨了外汇市场的价格过度反应。它采用动态触发方法来检测过度反应,然后使用各种统计方法,包括累积异常回报分析,来检验以下假设:过度反应日的小时回报的日内行为与正常日不同(H1),过度反应日的日内价格动态存在可检测的模式(H2),以及随后几天的日内价格动态存在可检测的模式(H3)。结果表明,过度反应日和正常日的日内动态之间存在统计学上的显著差异;此外,价格在过度反应日倾向于朝着过度反应的方向变化,但在第二天则朝着相反的方向移动。最后,存在通过利用检测到的异常来产生异常利润的交易策略,这可以被视为市场效率低下的证据。


IV. 回测表现
| 年化回报 | 4.78% |
| 波动率 | 6.3% |
| β值 | 0.143 |
| 夏普比率 | 0.76 |
| 索提诺比率 | -0.197 |
| 最大回撤 | N/A |
| 胜率 | 47% |
V. 完整的 Python 代码
from AlgorithmImports import *
class PriceOverreactionsintheForex(QCAlgorithm):
def initialize(self):
self.set_start_date(2009, 1, 1)
self.set_cash(100000)
self.period: int = 50
self.symbol: Symbol = self.add_forex('AUDUSD', Resolution.MINUTE, Market.OANDA).symbol
self.securities[self.symbol].set_fee_model(CustomFeeModel())
self.daily_returns: RollingWindow = RollingWindow[float](self.period)
self.open_price: float | None = None
self.settings.minimum_order_margin_portfolio_percentage = 0.
self.schedule.on(self.date_rules.every_day(self.symbol), self.time_rules.at(17, 0), self.at17)
def at17(self):
history : dataframe = self.history(self.symbol, self.period, Resolution.DAILY)
if len(history) == self.period:
if 'close' in history:
closes: np.ndarray = np.array(history['close'].values)
daily_returns: np.ndarray = closes[1:] / closes[:-1] - 1
avg_ret: float = np.average(daily_returns)
std: float = np.std(daily_returns)
price: float = self.securities[self.symbol].close
ret: float = price / closes[-1] - 1
if ret > avg_ret + 2*std:
self.set_holdings(self.symbol, 1)
holdings_q: float = self.portfolio[self.symbol].quantity
self.market_on_close_order(self.symbol, -holdings_q)
# Custom fee model
class CustomFeeModel(FeeModel):
def get_order_fee(self, parameters):
fee = parameters.security.price * parameters.order.absolute_quantity * 0.00005
return OrderFee(CashAmount(fee, "USD"))