AuthorJing Wu2018-08-23


The lunar phase is the shape of the direct sunlight portion of the Moon as viewed from Earth. The lunar phases gradually and cyclically change over the period of a month. Lunar phases have proven effects on human biology and psychology. Investors are subject to various psychological and behavioral biases and mood fluctuations. Therefore, if lunar phases affect mood, by extension, these phases may affect investor behavior and thus asset prices. This tutorial we will build an algorithm based upon the Moon phase.


The lunar calendar data is obtained from the United States Naval Observatory (USNO) website. We import the custom data as a CSV file. The four phases of the lunar cycle are New Moon, First Quarter, Full Moon, and Last Quarter. They are in string format in the data file so we convert the string names to numbers as New Moon(0), First Quarter(1), Full Moon(2) and Last Quarter(3).

class MoonPhase(PythonData):
    "Class to import Phases of the Moon data from Dropbox"

    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("", SubscriptionTransportMedium.RemoteFile)

    def Reader(self, config, line, date, isLiveMode):
        index = MoonPhase()
        index.Symbol = config.Symbol
            # Example File Format: (Data starts from 01/07/2004)
            # date                 phase
            # 2004 Jan 07 15:40    Full Moon
            data = line.split(',')
            if data[0] == "date": return None
            index.Time = datetime.strptime(data[0], "%Y %b %d %H:%M").replace(hour=0, minute=0)
            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
            return None

        return index

Research shows that the effect is strongest in emerging markets. Here we choose the iShares MSCI Emerging Markets Index ETF, EEM. The algorithm therefore goes long in emerging market index ETF 7 days before the new moon and switch to a short position on ETF 7 days before the full moon. The benchmark is set to EEM.

def Initialize(self):
    self.SetStartDate(2004, 1, 1)
    self.SetEndDate(2018, 8, 1)
    # import the custom data
    self.AddData(MoonPhase, "phase", Resolution.Daily)
    self.AddEquity("EEM", Resolution.Daily)

def OnData(self, data):
    # long in emerging market index ETF 7 days before the new moon (It's the Last Quarter)
    if self.Securities["phase"].Price == 3 and not self.Portfolio["EEM"].IsLong:
        self.SetHoldings("EEM", 1)
    # short on emerging market index ETF 7 days before the full moon (It's the First Quarter)
    elif self.Securities["phase"].Price == 1 and not self.Portfolio["EEM"].IsShort:
        self.SetHoldings("EEM", -1)


Previous: Combining Momentum Effect with Volume Next: ROA Effect within Stocks