该策略使用月历,在新月前七天做多黄金,并在满月前七天转换为现金。

I. 策略概述

该策略使用月历(如来自美国海军天文台网站的月历),将一个农历月分为两个阶段:新月(14天)和满月(14天)。策略在新月前七天对黄金进行多头配置,并在满月前七天转换为现金。

II. 策略合理性

心理学研究提供了多种理论,探讨情绪如何影响人们的认知与偏好。有证据表明,月相周期会对人类情绪和行为产生影响,这可能适度地影响资产的回报率。

III. 论文来源

Lunar Seasonality in Precious Metal Returns? [点击浏览原文]

<摘要>

本文首次展示了月相周期对贵金属回报率的影响。这种效应在白银中表现得尤为显著,而在黄金中相对较弱,在铂金中几乎没有证据表明存在此效应。

IV. 回测表现

年化收益率5.2%
波动率N/A
Beta0.019
夏普比率N/A
索提诺比率-0.096
最大回撤N/A
胜率51%

V. 完整python代码

from AlgorithmImports import *
from QuantConnect.Data import SubscriptionDataSource
from QuantConnect.Python import PythonData
#endregion
class LunarCycleinPreciousMetals(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2004, 1, 1)
        self.SetCash(100000)
        self.lunar_phase:Symbol = self.AddData(MoonPhase, "phase", Resolution.Daily).Symbol
        self.symbol = self.AddEquity("GLD", Resolution.Daily).Symbol
        self.settings.daily_precise_end_time = False
    
    def OnData(self, data):
        if self.Securities[self.lunar_phase].GetLastData() and self.Time.date() > MoonPhase.get_last_update_date():
            self.Liquidate(self.symbol)
        if self.symbol in data and data[self.symbol]:
            if self.securities[self.lunar_phase].get_last_data():
                # long in emerging market index ETF 7 days before the new moon (It's the Last Quarter)
                if self.securities[self.lunar_phase].get_last_data().value == 3 and not self.Portfolio[self.symbol].IsLong:
                    self.SetHoldings(self.symbol, 1)
            
                # short on emerging market index ETF 7 days before the full moon (It's the First Quarter)
                elif self.securities[self.lunar_phase].get_last_data().value == 1 and not self.Portfolio[self.symbol].IsShort:
                    self.SetHoldings(self.symbol, -1)
        
class MoonPhase(PythonData):
    _last_update_date:datetime.date = datetime(1,1,1).date()
    @staticmethod
    def get_last_update_date() -> datetime.date:
       return MoonPhase._last_update_date
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("data.quantpedia.com/backtesting_data/calendar/moon_phase.csv", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLiveMode):
        index = MoonPhase()
        index.Symbol = config.Symbol
        try:
            # Source: https://www.timeanddate.com/moon/phases/?year=2023
            # Example File Format: (Data starts from 01/07/2004)
            # date;phase
            # 2004-01-07;Full Moon
            # 2004-01-15;Last Quarter
            data = line.split(';')
            if data[0] == "date": return None
            index.Time = datetime.strptime(data[0], "%Y-%m-%d")
            if data[1] == "New Moon":
                index.Value = 0
            elif data[1] == "First Quarter":
                index.Value = 1
            elif data[1] == "Full Moon":
                index.Value = 2
            elif data[1] == "Last Quarter":
                index.Value = 3
            if index.Time.date() > MoonPhase._last_update_date:
                MoonPhase._last_update_date = index.Time.date()
        except:
            return None
            
        return index




发表评论

了解 Quant Buffet 的更多信息

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

继续阅读