def testFairSpread(self):
       marketDataContainer = MarketDataContainer()
       marketData = self._pos.marketData(self._pricingDate, self._marketId)
       marketDataContainer.add(marketData)
       self._pos.setMarketDataContainer(marketDataContainer)
 #      print round(self._pos.fairSpread(self._pricingDate, self._marketId),2)
       self.failIf(round(self._pos.fairSpread(self._pricingDate, self._marketId),2) <> 0.0)
 def testNPV(self):
     marketDataContainer = MarketDataContainer()
     marketData = self._pos.marketData(self._pricingDate, self._marketId)
     marketDataContainer.add(marketData)
     self._pos.setMarketDataContainer(marketDataContainer)
 #    print round(self._pos.NPV(self._pricingDate, self._marketId),2)
     self.failIf(round(self._pos.NPV(self._pricingDate, self._marketId),2) <> -5044.78)
Beispiel #3
0
    def fct1(self,x):
#        print '__________________' + str(x)
        
        position = BondPosition(amount=1,tCBond=self.tCBond)
        marketDataContainer = MarketDataContainer()
        marketData = position.marketData(self.pricingDate, self.marketId)
#         #print marketData
        for m in marketData:
            if m.__class__ == BondOAS:
                m.mid = x[0]
        marketDataContainer.add(marketData)
        position.setMarketDataContainer(marketDataContainer)
        npv = position.NPV(self.pricingDate, self.marketId)
        result = math.fabs(npv-self.price)
#        print npv
 #       print self.price
        return result
    def calc(self):
#        print 'in calc'
        startDjangoPositions = ModelPosition.objects.filter(portfolio=self.portfolio, asOf=self.start)
        for djangoPosition in startDjangoPositions:
            position = CreatePosition(djangoPosition)
            self.portfolio.addPosition(position)
        marketDataContainer = MarketDataContainer()
        for position in self.portfolio.positions:
 #           print position
            marketDataContainer.add(position.marketData(pricingDate=self.start, marketId=self.marketId))
        for position in self.portfolio.positions:
            position.marketDataContainer = marketDataContainer
        self.startValue = self.portfolio.NPV(pricingDate=self.start,marketId=self.marketId)
  #      print 'Start value = %f' % self.startValue
        
        endPortfolio =Portfolio.objects.get(name=self.portfolio.name,user=self.portfolio.user)
        endDjangoPositions = ModelPosition.objects.filter(portfolio=endPortfolio, asOf=self.end)
        for djangoPosition in endDjangoPositions:
            position = CreatePosition(djangoPosition)
            endPortfolio.addPosition(position)
        marketDataContainer = MarketDataContainer()
        for position in endPortfolio.positions:
            marketDataContainer.add(position.marketData(pricingDate=self.end, marketId=self.marketId))
        for position in endPortfolio.positions:
            position.marketDataContainer = marketDataContainer
        self.endValue = endPortfolio.NPV(pricingDate=self.end,marketId=self.marketId)
   #     print 'End portfolio value = %f' % self.endValue

        #Adjust all positions but Cash ADD and REMOVE transactions so that I do not count them
        #We ignore the interest effect of these transactions
        transactions = Transaction.objects.filter(portfolio=endPortfolio,
                                                  transactionType = TransactionType('ADD'),
                                                  positionType = PositionType('CASH'),
                                                  ticker = 'Cash',
                                                  transactionDate__range=[self.start,self.end])

        #print transactions
        for transaction in transactions:
            self.transactionValue -= transaction.amount
            
        transactions = Transaction.objects.filter(portfolio=endPortfolio,
                                                  transactionType = TransactionType('REMOVE'),
                                                  positionType = PositionType('CASH'),
                                                  ticker = 'Cash',
                                                  transactionDate__range=[self.start,self.end])
        #print transactions
        for transaction in transactions:
            self.transactionValue += transaction.amount

        self.endValue += self.transactionValue
        #print 'Effective end value = %f' % self.endValue
        try:
            self.annualPerformance = ((self.endValue - self.startValue) / self.startValue) * \
                                    365.0 / (self.end.ql() - self.start.ql())   
        except ZeroDivisionError:
            self.annualPerformance = 0
        self.periodPerformance = self.annualPerformance * (self.end.ql() - self.start.ql()) / 365.0
        #print 'Annualized Performance is %f' % self.annualPerformance
        self.upToDate = True
 def __init__(self, pricingDate = None, portfolio = None, timeSteps = None,
              confidenceInterval = None, marketId = ''):
     '''
     Input: pricingDate, portfolio, timeSteps
     timeSteps is HVARTimeStepData object and defines start, end, and all dates
     '''
     if timeSteps == None:
         raise OtherException('timeSteps cannot be none')
     self.pricingDate = pricingDate
     self.start = timeSteps.start
     self.end = timeSteps.end
     self.timeStepDataList = []
     for item in timeSteps.timeSteps:
         self.timeStepDataList.append(HVARTimeStepData(date = item))
     self.portfolio = portfolio
     self.marketId = marketId
     self.todaysMarketDataContainer = MarketDataContainer()
     self.confidenceInterval = confidenceInterval
     self.upToDate = False
     self.pnls = []
     self.returns = []
    def testPriceWith2Curves(self):
        marketDataContainer = MarketDataContainer()
        marketData = self._pos.marketData(self._pricingDate, self._marketId)
#        print marketData[0].buildZeroCurve().nodes()
        marketDataContainer.add(marketData)
        self._pos.setMarketDataContainer(marketDataContainer)
        price1 = round(self._pos.NPV(self._pricingDate, self._marketId),5)
 #       print price1
        marketData[0].shift(0.01)
#        print marketData[0].buildZeroCurve().nodes()
        marketDataContainer1 = MarketDataContainer()
        marketDataContainer1.add(marketData)
        self._pos.setMarketDataContainer(marketDataContainer1)
        #add dirty flag to position to run setupql again. add add marketdatacontainer method
        price2 = round(self._pos.NPV(self._pricingDate, self._marketId),5)
#        print price2
        self.failIf(price1 == price2)
 def testCalculatePerformanceTEST1Portfolio1Y(self):
     #load portfolio as of start and value
     #load portfolio as of end and value
     #sum up all ADD and REMOVE Transaction
     #% return = {end - start + SUM(ADD) - SUM(REMOVE)} / Start
     startPortfolio =Portfolio.objects.get(name='TEST1')
     start = Date(month=8,day=30,year=2011)
     startDjangoPositions = ModelPosition.objects.filter(portfolio=startPortfolio, asOf=start)
     for djangoPosition in startDjangoPositions:
         position = CreatePosition(djangoPosition)
         startPortfolio.addPosition(position)
     marketDataContainer = MarketDataContainer()
     for position in startPortfolio.positions:
         marketDataContainer.add(position.marketData(pricingDate=start, marketId=self.marketId))
     for position in startPortfolio.positions:
         position.marketDataContainer = marketDataContainer
     startValue = startPortfolio.NPV(pricingDate=start,marketId=self.marketId)
     print 'Start value = %f' % startValue
     
     endPortfolio =Portfolio.objects.get(name='TEST1')
     end = Date(month=9,day=12,year=2011)
     endDjangoPositions = ModelPosition.objects.filter(portfolio=endPortfolio, asOf=end)
     for djangoPosition in endDjangoPositions:
         position = CreatePosition(djangoPosition)
         endPortfolio.addPosition(position)
     marketDataContainer = MarketDataContainer()
     for position in endPortfolio.positions:
         marketDataContainer.add(position.marketData(pricingDate=end, marketId=self.marketId))
     for position in endPortfolio.positions:
         position.marketDataContainer = marketDataContainer
     endValue = endPortfolio.NPV(pricingDate=end,marketId=self.marketId)
     print 'End value = %f' % endValue
     
     #Should add the looping over transactions that are ADD and REDUCE
     
     print 'Annualized Performance is %f' % (((endValue - startValue) / startValue) * 365.0 / (end.ql() - start.ql()))
class HistoricalVAR(cmt.cmt):
    '''
    Analysis to calculate Historical VAR
    '''
    def __init__(self, pricingDate = None, portfolio = None, timeSteps = None,
                 confidenceInterval = None, marketId = ''):
        '''
        Input: pricingDate, portfolio, timeSteps
        timeSteps is HVARTimeStepData object and defines start, end, and all dates
        '''
        if timeSteps == None:
            raise OtherException('timeSteps cannot be none')
        self.pricingDate = pricingDate
        self.start = timeSteps.start
        self.end = timeSteps.end
        self.timeStepDataList = []
        for item in timeSteps.timeSteps:
            self.timeStepDataList.append(HVARTimeStepData(date = item))
        self.portfolio = portfolio
        self.marketId = marketId
        self.todaysMarketDataContainer = MarketDataContainer()
        self.confidenceInterval = confidenceInterval
        self.upToDate = False
        self.pnls = []
        self.returns = []
        
    @log
    def generateTodaysMarketDataContainer(self):
        ''' 
        Generate today's market data for portfolio 
        '''
        for position in self.portfolio.positions:
            self.todaysMarketDataContainer.add(position.marketData(self.pricingDate, self.marketId))

    @log
    def generateAllHistoricalMarketDataContainers(self):
        '''
        Generates all market data containers for each time step
        '''
        for timeStep in self.timeStepDataList:
            for position in self.portfolio.positions:
                timeStep.marketDataContainer.add(position.marketData(timeStep.date, self.marketId))
                #scenario market data is based on as of market data. Shift is applied later
                timeStep.scenarioMarketDataContainer.add(position.marketData(self.pricingDate, self.marketId))
#        print '****Debug output HVAR*****'
#        for timeStep in self.timeStepDataList:
#            for m, s in zip(timeStep.marketDataContainer.marketDataList,
#                            timeStep.scenarioMarketDataContainer.marketDataList):
#                print m
#                print s
#        print '****Debug output HVAR done*****'

    @log
    def generateAllMarketDataShifts(self):
        first = True
        for timeStep in self.timeStepDataList:
            if first:
                prevTimeStep = timeStep
                first = False
                continue
            else:
                for marketData, prevMarketData in zip(timeStep.marketDataContainer.marketDataList,
                                                      prevTimeStep.marketDataContainer.marketDataList):
                    timeStep.shifts.append(marketData.createShiftCurve(prevMarketData))
                prevTimeStep = timeStep
                
    @log 
    def generateAllScenarios(self):
        first = True
        for timeStep in self.timeStepDataList:
            if first:
                first = False
                continue
            else:
                for marketData, shift in zip(timeStep.scenarioMarketDataContainer.marketDataList, 
                                             timeStep.shifts):
                    marketData.adjustWithShiftCurve(shift)
    
    @log
    def generateBaseValues(self):
        for position in self.portfolio.positions:
            position.setMarketDataContainer(self.todaysMarketDataContainer)
        value = self.portfolio.NPV(self.pricingDate, self.marketId)
        for timeStep in self.timeStepDataList:
            timeStep.value = value

    @log
    def generatePnls(self):
        first = True
        for timeStep in self.timeStepDataList:
            for position in self.portfolio.positions:
                position.setMarketDataContainer(timeStep.scenarioMarketDataContainer)
            value = self.portfolio.NPV(self.pricingDate, self.marketId)
            if first:
                timeStep.pnl = None
                first = False
            else:
                timeStep.pnl = value - timeStep.value
        
    @log
    def generateReturns(self):
        first = True
        for timeStep in self.timeStepDataList:
            if first:
                timeStep.percentReturn = None
                first = False
            else:
                timeStep.percentReturn = timeStep.pnl / timeStep.value

    @log
    def generateReturnsAndPnlsForStats(self):
        first = True
        for timeStep in self.timeStepDataList:
            if first:
                first = False
            else:
                self.pnls.append(timeStep.pnl)
                self.returns.append(timeStep.percentReturn)
                
    @log    
    def doAnalysis(self):
        '''
        Run historical VaR analysis. Can be re-run any time
        '''
#the following algorithm should be implemented:
#load today's position and today's market data
#generate shifts of market data for all time periods
#generate scenarios with shifts and today's market data
#run scenario analysis with simultaneous shifts
#output of scenario analysis is pnl vector
        self.generateTodaysMarketDataContainer()
        
        self.generateAllHistoricalMarketDataContainers()
        
        self.generateBaseValues()
        
        self.generateAllMarketDataShifts()

        self.generateAllScenarios()
     
        self.generatePnls()
        
        self.generateReturns()

        self.generateReturnsAndPnlsForStats()
        
        self.upToDate = True

    @log
    def getPnLList(self):
        '''
        Returns list of pnl values. Becuase pnl on first timestep is None
        we do not return it
        '''
        if self.upToDate == False:
            self.doAnalysis()
        return self.pnls
    @log
    def getDateList(self):
        '''
        Returns list of dates from timeSteps. This list includes the 
        first date. So, thi slist is one item longer than pnls and returns
        '''
        return [timeStep.date for timeStep in self.timeStepDataList]

    @log
    def getPercentile(self):
        '''
        Returns list of pnl values. Becuase pnl on first timestep is None
        we do not return it
        '''
        if self.upToDate == False:
            self.doAnalysis()
        return scipy.stats.scoreatpercentile(self.returns,100.0*(1-self.confidenceInterval))        
    @log
    def getMean(self):
        if self.upToDate == False:
            self.doAnalysis()
        return scipy.stats.nanmean(self.returns)
    @log
    def getStdDev(self):
        if self.upToDate == False:
            self.doAnalysis()
        return scipy.stats.moment(self.returns, 2)
    @log
    def run(self):
        return self.getPercentile()
Beispiel #9
0
    def run(self):
        #Log
        if os.path.isfile(self.logFile):
            os.remove(self.logFile)
        logFileHandle = open(self.logFile,'w')
        logFileHandle.write('Running batch as of %s\n' % self.batchDate)
        logFileHandle.write('Max batch is %s\n' % self.maxBatchDate)
#        if QuantLib.TARGET().isBusinessDay(self.batchDate.ql()) == False:
 #           logFileHandle.write('Not a good business date based on QuantLib TARGET calendar. Exiting ...')
  #          print('Not a good business date based on QuantLib TARGET calendar. Exiting ...')
        
        #Update locations with date
        logFileHandle.write('\nUpdating all locations except TEST1 with new date\n')
        locations = Location.objects.filter(~Q(name='TEST1'))
        for location in locations:
            logFileHandle.write('Updating location %s\n' % location.name)
            location.pricingDate = self.batchDate.toPythonDate()
            location.save()
        
        #Load Equity prices
        logFileHandle.write('\nLoading equity prices\n')
        equities = Equity.objects.all()
        equityLoader = EquityPriceLoader()
        for equity in equities:
            #skip TEST1 and TEST2 as they are only used for testing
            if equity.ticker in ['TEST1', 'TEST2']:
                continue
            if StockPrice.objects.filter(equity=equity, pricingDate=self.batchDate, marketId=self.marketId).exists() == True:
                logFileHandle.write('%s price exists\n' % equity.ticker)
                continue
            else:
                logFileHandle.write('Loading prices for equity %s\n' % equity.ticker)
                try:
                    equityLoader.loadCurrentPriceFromYahoo(secId=equity.ticker, 
                                                           today=self.batchDate,
                                                           marketId=self.marketId)
                except MarketDataMissing:
                    logFileHandle.write('No market data loaded for %s as of %s\n' % (equity.ticker, self.batchDate))
                    logFileHandle.write('As default loading price from last batch date\n')
                    lastPrice = StockPrice.objects.get(equity=equity, pricingDate=self.maxBatchDate, marketId=self.marketId)
                    lastPrice.pricingDate = self.batchDate
                    lastPrice.pk = None
                    lastPrice.save()
                   
        #Load Interest Rates        
        logFileHandle.write('\nLoading Interest Rates\n')
        if self.maxBatchDate != self.batchDate:
            logFileHandle.write('For now just copy rates from max batch date to current batch date\n')
            curve = InterestRateCurve.objects.get(ccy=Currency('USD'), index=Index('LIBOR'), 
                                                  term=TimePeriod('M'), numTerms=3, 
                                                  pricingDate=self.maxBatchDate, 
                                                  marketId='EOD')
            curve.loadRates()
            
            newCurve = InterestRateCurve(ccy=Currency('USD'), index=Index('LIBOR'), 
                                         term=TimePeriod('M'), numTerms=3, 
                                         pricingDate=self.batchDate, 
                                         marketId='EOD')
            
            for rate in curve.getRates():
                newRate = InterestRate(type=rate.type, term=rate.term, numTerms=rate.numTerms, mid=rate.mid, curve=newCurve)
                logFileHandle.write('Rate: %s/%d/%0.2f\n' % (rate.term, rate.numTerms, rate.mid*100))
                newCurve.addRate(newRate)
            newCurve.save()

        #Copy OAS forward and keep constant
        logFileHandle.write('\nCopying OAS from max batch date to batch date\n')
        if self.maxBatchDate != self.batchDate:
            bondOAS = BondOAS.objects.get(tCBond=TCBond.objects.get(name='PortAuth_4.00_JAN42'),
                                          marketId='EOD', pricingDate=self.maxBatchDate)
            bondOAS.pk = None
            bondOAS.pricingDate = self.batchDate
            bondOAS.save()
            
        #Process Positions
        logFileHandle.write('\nProcessing positions\n')
        #load all positions with the max date
        #if the batchDate greater than maxbatchdate then copy position to batchdate (roll position forward)
        if self.maxBatchDate < self.batchDate:
            positions = ModelPosition.objects.filter(asOf=self.maxBatchDate)
            for position in positions:
                logFileHandle.write('Copying position %s from max batch date to batch date\n' % position)
                position.pk = None
                position.asOf = self.batchDate
                position.save()

        #Update Positions based on Transactions
        logFileHandle.write('\nUpdating of positions based on transaction\n')
        transactions = Transaction.objects.filter(reflectedInPosition=False)
        if len(transactions) == 0:
            logFileHandle.write('No transactions to process\n')
        else:
            for transaction in transactions:
                logFileHandle.write('Processing transaction %s\n' % str(transaction))
                positions = transaction.relatedPositions()
                for position in positions:
                    logFileHandle.write('Processing position %s\n' % str(transaction))
                    transaction.updatePositionAmount(position=position)  
                    position.save() 
                transaction.reflectedInPosition = 'True'
                transaction.save()                 
            
        #Performance
        logFileHandle.write('\nRunning Performance Report\n')
        if os.path.isfile(self.perfFile):
            os.remove(self.perfFile)
        perfFileHandle = open(self.perfFile,'w')
        portfolios = Portfolio.objects.filter(user='******')
        startValue = 0
        endValue = 0
        for portfolio in portfolios:
            performanceCalculator = PerformanceCalculator(start=self.productionStartDate,
                                                          end=self.batchDate,
                                                          portfolio=portfolio,
                                                          marketId=self.marketId)
            perfFileHandle.write(performanceCalculator.report()+'\n')
            startValue += performanceCalculator.startValue
            endValue += performanceCalculator.endValue
            endValue += performanceCalculator.transactionValue
        
        if startValue == 0 or (self.batchDate.ql() - self.productionStartDate.ql()) == 0:
            overallPerformance = 0
        else:
            overallPerformance = ((endValue - startValue) / startValue) * 365.0 / (self.batchDate.ql() - self.productionStartDate.ql())
        perfFileHandle.write('Overall Period Performance = %.2f%%\n' % (overallPerformance*100.0/365.0*(self.batchDate.ql() - self.productionStartDate.ql())))
        perfFileHandle.write('Overall Annual Performance = %.2f%%' % (overallPerformance*100.0))
        perfFileHandle.close()
        
        #MTM and Positions
        logFileHandle.write('\nRunning MTM and Positions Report\n')
        totalValue = 0
        if os.path.isfile(self.mtmFile):
            os.remove(self.mtmFile)
        mtmFileHandle = open(self.mtmFile,'w')
        portfolios =Portfolio.objects.filter(user='******')
        mtmFileHandle.write('MTM Report as of %s\n' % self.batchDate)
        for portfolio in portfolios:
            mtmFileHandle.write('Portfolio=%s\n' % portfolio.name)
            modelPositions = ModelPosition.objects.filter(portfolio=portfolio, asOf=self.batchDate)
            for modelPosition in modelPositions:
                position = CreatePosition(modelPosition=modelPosition)
                portfolio.addPosition(position)
            marketDataContainer = MarketDataContainer()
            for position in portfolio.positions:
                marketDataContainer.add(position.marketData(pricingDate=self.batchDate, marketId=self.marketId))
            for position in portfolio.positions:
                position.marketDataContainer = marketDataContainer
            for position in portfolio.positions:
                positionValue = position.NPV(pricingDate=self.batchDate,marketId=self.marketId)
                mtmFileHandle.write('ModelPosition=%s with %.0f shares, asset type %s and value $%s\n' % (position.secId,
                                                                                                   position.amount,
                                                                                                   position.getAssetType(),
                                                                                                   fToDC(positionValue)))
            portfolioValue = portfolio.NPV(pricingDate=self.batchDate,marketId=self.marketId)
            mtmFileHandle.write('Portfolio value=$%s\n\n' % fToDC(portfolioValue))
            totalValue += portfolioValue
        mtmFileHandle.write('Total value=%s\n\n' % fToDC(totalValue))

        #Asset Allocation
        #allocations is associative array with value
        allocations = {}
        totalValue = 0
        for item in AssetType.choices:
            allocations[item[0]] = 0
        logFileHandle.write('\nRunning Allocation Report\n\n')
        if os.path.isfile(self.allocationFile):
            os.remove(self.allocationFile)
        allocationFileHandle = open(self.allocationFile,'w')
        portfolios =Portfolio.objects.filter(user='******')
        allocationFileHandle.write('Allocation Report as of %s\n\n' % self.batchDate)
        for portfolio in portfolios:
            if portfolio.name == 'TradeAug2013':
                continue
            modelPositions = ModelPosition.objects.filter(portfolio=portfolio, asOf=self.batchDate)
            for modelPosition in modelPositions:
                position = CreatePosition(modelPosition)
                portfolio.addPosition(position)
            marketDataContainer = MarketDataContainer()
            for position in portfolio.positions:
                marketDataContainer.add(position.marketData(pricingDate=self.batchDate, marketId=self.marketId))
            for position in portfolio.positions:
                position.marketDataContainer = marketDataContainer
            for position in portfolio.positions:
                npv = position.NPV(pricingDate=self.batchDate, marketId=self.marketId)
                allocations[str(position.getAssetType())] += npv
                totalValue += npv
        
        orderedAllocations = OrderedDict(sorted(allocations.items(),key=lambda t: t[1],reverse=True))
        for key in orderedAllocations.keys():
            try:
                allocationPercent = Allocation.objects.get(assetType=AssetType(key)).percent
            except:
                allocationPercent = 0.0
            try:
                actualAllocation = 100*orderedAllocations[key]/totalValue
            except:
                actualAllocation = 0.0
            allocationFileHandle.write('%s=%.0f%%\t\t\t\t\t\twith target %.0f%%\t and value $%s\n' % (key,
                                                                                           actualAllocation,
                                                                                           100*allocationPercent,
                                                                                           fToD(orderedAllocations[key])))
        
        logFileHandle.write('Batch completed\n')
        logFileHandle.close()
        
        #Every time I run the batch and it succeeds we need to save the batch info
        self.batch.save()