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)
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()
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()