Overall Statistics
# https://quantpedia.com/strategies/dollar-carry-trade/
#
# The investment universe consists of currencies from developed countries (the Euro area, Australia, Canada, Denmark, Japan, New Zealand, Norway, Sweden,
# Switzerland, and the United Kingdom). The average forward discount (AFD) is calculated for this basket of currencies (each currency has an equal weight).
# The average 3-month rate could be used instead of the AFD in the calculation. The AFD is then compared to the 3-month US Treasury rate. The investor
# goes long on the US dollar and goes short on the basket of currencies if the 3-month US Treasury rate is higher than the AFD. The investor goes short
# on the US dollar and long on the basket of currencies if the 3-month US Treasury rate is higher than the AFD. The portfolio is rebalanced monthly.

from datetime import datetime
import pandas as pd

class Dollar_Carry_Trade(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2001, 1, 1)
        self.SetEndDate(2019, 1, 1)
        self.SetCash(100000)
        
        self.avg_bond_yields = pd.read_csv('https://docs.google.com/spreadsheets/d/15GO61pfTKSaAr4tNmHkxyW7JeXWiFxuCBemdC_tZSvU/export?format=csv', dtype={'date':str}, index_col='date') #   header=None)
        
        self.symbols = ["CME_AD1", # Australian Dollar Futures, Continuous Contract #1
                        "CME_BP1", # British Pound Futures, Continuous Contract #1
                        "CME_CD1", # Canadian Dollar Futures, Continuous Contract #1
                        "CME_EC1", # Euro FX Futures, Continuous Contract #1
                        "CME_JY1", # Japanese Yen Futures, Continuous Contract #1
                        "CME_MP1", # Mexican Peso Futures, Continuous Contract #1
                        #"CME_NE1",# New Zealand Dollar Futures, Continuous Contract #1    # Short history ~2007
                        "CME_SF1" # Swiss Franc Futures, Continuous Contract #1
                        ]
        # True -> Quantpedia data
        # False -> Quandl free data
        self.use_quantpedia_data = True
        
        if not self.use_quantpedia_data:
            self.symbols = ['CHRIS/' + x for x in self.symbols]
        
        for symbol in self.symbols:
            data = None
            if self.use_quantpedia_data:
                data = self.AddData(QuantpediaFutures, symbol, Resolution.Daily)
            else:
                data = self.AddData(QuandlFutures, symbol, Resolution.Daily)
            #data.SetLeverage(2)
            #self.data[symbol] = deque(maxlen=self.lookup_period)
            
        self.Schedule.On(self.DateRules.MonthStart(self.symbols[0]), self.TimeRules.AfterMarketOpen(self.symbols[0]), self.Rebalance)

    def Rebalance(self):
    
        date = str(self.Time.month) + '/' + str(self.Time.year)
        current_row_index = self.avg_bond_yields.index.get_loc(date)
        row = self.avg_bond_yields.iloc[current_row_index - 1]

        treasuries_3m_rate = row['treasuries']
        average = row['average']
        
        self.Liquidate()

        count = len(self.symbols)
        if treasuries_3m_rate > average:
            # long on the US dollar and goes short on the basket of currencies 
            for symbol in self.symbols:
                self.SetHoldings(symbol, -1/count)
        else:
            # short on the US dollar and long on the basket of currencies
            for symbol in self.symbols:
                self.SetHoldings(symbol, 1/count)

# Quantpedia data
class QuantpediaFutures(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("http://data.quantpedia.com/backtesting_data/futures/{0}.csv".format(config.Symbol.Value), SubscriptionTransportMedium.RemoteFile, FileFormat.Csv)

    def Reader(self, config, line, date, isLiveMode):
        data = QuantpediaFutures()
        data.Symbol = config.Symbol
        
        try:
            if not line[0].isdigit(): return None
            split = line.split(';')
            
            data.Time = datetime.strptime(split[0], "%d.%m.%Y") + timedelta(days=1)
            data['settle'] = float(split[1])
            data.Value = float(split[1])
        except:
            return None
            
        return data

# Quandl free data
class QuandlFutures(PythonQuandl):
    def __init__(self):
        self.ValueColumnName = "settle"