该策略使用利率差动量信号交易11个主要货币对,并在伦敦与纽约市场收盘时进行每日两次再平衡,以利用基于利率驱动的市场低效性。

I. 策略概述

交易范围:

涉及11个主要货币对,包括:AUD、CAD、CHF、DKK、EUR、GBP、JPY、NOK、NZD、SEK、USD。

信号生成:

通过动态调整仓位,该策略捕捉由利率差异引发的外汇市场动量。

II. 策略合理性

该策略通过系统性买入利率预期上升的货币并卖出预期下降的货币,利用这些市场低效性获利

III. 论文来源

ANANTA: A Systematic Quantitative FX Trading Strategy [点击浏览原文]

<摘要>

本文是系列研究的第一篇,旨在详细研究ANANTA策略,这是一种使用固定收益信号的短期系统化外汇模型。本部分重点描述策略的背景及基本实施方法,包括交易假设、信号构建及结果分析。

IV. 回测表现

年化收益率9.01%
波动率5.54%
Beta-0.075
夏普比率1.63
索提诺比率N/A
最大回撤N/A
胜率46%

V. 完整python代码

import data_tools
from AlgorithmImports import *
import numpy as np
class InterestRatesMomentumPredictsFXRates(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2000, 1, 1)
        self.SetCash(100000)
        
        # Country symbol and currency future symbol.
        self.symbols = {
                        "USD" : "not_traded", # US Dollar index Futures, Continuous Contract #1
                        "EUR" : "CME_EC1", # Euro FX Futures, Continuous Contract #1
                        "GBP" : "CME_BP1", # British Pound Futures, Continuous Contract #1
                        "CHF" : "CME_SF1", # Swiss Franc Futures, Continuous Contract #1
                        "JPY" : "CME_JY1", # Japanese Yen Futures, Continuous Contract #1
                        }
        # Interest rate data.
        self.interest_rate = self.AddData(data_tools.InterestRate, 'InterestRate', Resolution.Daily).Symbol
        
        self.period = 15
        self.yield_difference = {}
        
        countries = [x[0] for x in self.symbols.items()]
        for i, country1 in enumerate(countries):
            for j, country2 in enumerate(countries):
                if i <= j: continue
                self.yield_difference[country1 + country2] = RollingWindow[float](self.period)
        for country, currency_future in self.symbols.items():
            # Currency futures data.
            data = self.AddData(data_tools.QuantpediaFutures, currency_future, Resolution.Daily)
            data.SetLeverage(10)
            data.SetFeeModel(data_tools.CustomFeeModel())
        
    def OnData(self, data):
        if not self.Securities.ContainsKey(self.interest_rate): return
        
        interest_rate_date = self.Securities[self.interest_rate].GetLastData()
        if not interest_rate_date: return
        
        # make sure interest data is still comming in
        if (self.Time.date() - interest_rate_date.Time.date()).days >= 5:
            self.Liquidate()
            return
        
        countries = [x[0] for x in self.symbols.items()]
        signal = {}
        for i, country1 in enumerate(countries):
            sub_signal = {}
            for j, country2 in enumerate(countries):
                if i <= j: continue
            
                index = country1 + country2
                yield1 = interest_rate_date[country1]
                yield2 = interest_rate_date[country2]
                diff = yield1 - yield2
                
                self.yield_difference[index].Add(diff)
                
                if self.yield_difference[index].IsReady:
                    avg_diff = np.mean([x for x in self.yield_difference[index]])
                    sub_signal[index] = (diff - avg_diff) / abs(avg_diff)
            
            if len(sub_signal) > 0:
                abs_percentile = np.percentile([abs(x[1]) for x in sub_signal.items()], 50)
                
                for signal_index, sig in sub_signal.items():
                    iter_country1 = signal_index[:3]
                    iter_country2 = signal_index[-3:]
                    if abs(sig) > abs_percentile:
                        if iter_country1 != 'USD':
                            iter_future1 = self.symbols[iter_country1]
                            if iter_future1 not in signal:
                                signal[iter_future1] = 0
                            signal[iter_future1] += np.sign(sig)
                            
                        if iter_country2 != 'USD':
                            iter_future2 = self.symbols[iter_country2]
                            if iter_future2 not in signal:
                                signal[iter_future2] = 0
                            signal[iter_future2] -= np.sign(sig)
        
        if len(signal) != 0:
            futures_invested = [x.Key.Value for x in self.Portfolio if x.Value.Invested]
            for currency_future in futures_invested:
                if currency_future not in signal:
                    self.Liquidate(currency_future)
            
            foo = 3
            
            for currency_future, country_signal in signal.items():
                self.SetHoldings(currency_future, country_signal)



发表评论

了解 Quant Buffet 的更多信息

立即订阅以继续阅读并访问完整档案。

继续阅读