def compute_underlying_security(portfolios, tracks, spots, portfolio, operation, inner_security, key_date, work_date=None): portfolio_id = str(portfolio.id) inner_container = SecurityContainer.objects.get(id=inner_security) if not tracks.has_key(inner_security): track = get_main_track_content(inner_container) tracks[inner_security] = track value = get_closest_value(tracks[inner_security], operation.value_date if work_date==None else work_date) if value==None: LOGGER.error("No NAV available for " + inner_container.name + " as of " + str(from_epoch(long(key_date)))) return None divisor = get_price_divisor(inner_container) portfolios[portfolio_id][key_date][inner_security]['price'] = value['value'] portfolios[portfolio_id][key_date][inner_security]['price_divisor'] = divisor spot_pf = 1.0 if inner_container.currency.short_name!=portfolio.currency.short_name and (not spots.has_key(inner_container.currency.short_name) or not spots[inner_container.currency.short_name].has_key(portfolio.currency.short_name)): spot_track = get_exchange_rate(inner_container.currency.short_name, portfolio.currency.short_name) if not spots.has_key(inner_container.currency.short_name): spots[inner_container.currency.short_name] = {} spots[inner_container.currency.short_name][portfolio.currency.short_name] = spot_track if inner_container.currency.short_name!=portfolio.currency.short_name and spots.has_key(inner_container.currency.short_name) and spots[inner_container.currency.short_name].has_key(portfolio.currency.short_name): value = get_closest_value(spots[inner_container.currency.short_name][portfolio.currency.short_name], operation.value_date if work_date==None else work_date) if value!=None: spot_pf = value['value'] else: LOGGER.error("No SPOT available for " + inner_container.currency.short_name + '/' + portfolio.currency.short_name + " as of " + str(from_epoch(long(key_date)))) return None portfolios[portfolio_id][key_date][inner_security]['price_pf'] = portfolios[portfolio_id][key_date][inner_security]['price'] * spot_pf portfolios[portfolio_id][key_date][inner_security]['price_pf_divisor'] = portfolios[portfolio_id][key_date][inner_security]['price'] * spot_pf / divisor portfolios[portfolio_id][key_date][inner_security]['spot_pf'] = spot_pf portfolios[portfolio_id][key_date][inner_security]['price_date'] = value['date'].strftime('%Y-%m-%d')
def create_security_credit(container, source, target, details, label, is_dividend=True): current_account_type = Attributes.objects.get(identifier='ACC_CURRENT', active=True) operation_type = Attributes.objects.get(identifier='OPE_TYPE_DIVIDEND' if is_dividend else 'OPE_TYPE_COUPON', active=True) operation = FinancialOperation() operation.name = ('Dividends' if operation_type.identifier=='OPE_TYPE_DIVIDEND' else 'Coupon') + ' on security ' + target['security'].name + ' of ' + str(target['price']) + ' per share' operation.short_name =('Dividends' if operation_type.identifier=='OPE_TYPE_DIVIDEND' else 'Coupon') + ' on security ' + target['security'].name operation.status = Attributes.objects.get(identifier='OPE_STATUS_EXECUTED', active=True) if not details.has_key('status') else details['status'] operation.operation_type = operation_type operation.creation_date = details['operation_date'] operation.operator = None operation.validator = None operation.source = get_account(container, details, current_account_type) operation.target = target['security'] operation.spot = details['spot_rate'] operation.repository = None divisor = get_price_divisor(target['security']) operation.quantity = target['quantity'] operation.amount = target['quantity'] * target['price'] * details['spot_rate'] / divisor operation.price = target['price'] operation.operation_date = details['trade_date'] operation.operation_pnl = operation.amount operation.value_date = details['value_date'] operation.termination_date = details['value_date'] operation.associated_operation = None operation.save() create_expenses(operation, operation.source, details['source_expenses']) create_expenses(operation, operation.source, details['target_expenses']) return operation
def get_exchange_rate(source_currency, destination_currency): currency = SecurityContainer.objects.filter(name__startswith=source_currency + destination_currency) if currency.exists(): currency = currency[0] else: threaded.bloomberg_data_query('NO_NEED', [source_currency + destination_currency + ' Curncy'], True) currency = SecurityContainer.objects.get(name__startswith=source_currency + destination_currency) divisor = get_price_divisor(currency) return get_main_track_content(currency, True, False, divisor)
def create_security_movement(container, source, target, details, label): current_account_type = Attributes.objects.get(identifier='ACC_CURRENT', active=True) security_account_type = Attributes.objects.get(identifier='ACC_SECURITY', active=True) operation = FinancialOperation() operation.name = label if label!=None else generate_security_movement_label(target, details) operation.short_name = generate_security_movement_short_label(target, details) operation.status = Attributes.objects.get(identifier='OPE_STATUS_EXECUTED', active=True) if not details.has_key('status') else details['status'] operation.operation_type = generate_security_movement_operation_type(details) operation.creation_date = details['operation_date'] operation.operator = None operation.validator = None operation.source = get_account(container, details, current_account_type) if details['impact_pnl'] else None operation.target = target['security'] if operation.target.status.identifer!='STATUS_ACTIVE': # Status cannot be executed on a pending security operation.status = Attributes.objects.get(identifier='OPE_STATUS_PENDING', active=True) if not details.has_key('status') else details['status'] operation.spot = details['spot_rate'] operation.repository = get_account(container, details, security_account_type) operation.quantity = target['quantity'] used_price = target['price'] if not details['impact_pnl'] and (used_price==None or used_price==0.0): track = get_main_track_content(target['security']) value = get_closest_value(track, dt.strptime(details['trade_date'], '%Y-%m-%d')) if value==None: LOGGER.warn(target['security'].name + " - Transaction does not have a correct price but no valid price could be found.") used_price = 0.0 else: LOGGER.warn(target['security'].name + " - Transaction does not have a correct price but a valid price could be found.") used_price = value['value'] divisor = get_price_divisor(target['security']) operation.amount = (target['quantity'] * used_price * details['spot_rate']) / divisor operation.price = target['price'] operation.operation_date = details['trade_date'] operation.operation_pnl = 0.0 operation.value_date = details['value_date'] operation.termination_date = details['value_date'] operation.associated_operation = None operation.save() if details['impact_pnl']: create_expenses(operation, operation.source, details['source_expenses']) create_expenses(operation, operation.source, details['target_expenses']) if details.has_key('accrued_interest'): if details['accrued_interest'].has_key('source') and details['accrued_interest']['source']!=None and details['accrued_interest']['source']!=0.0: create_accrued(operation, operation.source, details['accrued_interest']['source']) if details['accrued_interest'].has_key('target') and details['accrued_interest']['target']!=None and details['accrued_interest']['target']!=0.0: create_accrued(operation, operation.source, details['accrued_interest']['target']) return operation
def compute_valuation(self, container, frequency): #TODO Correct the bug with frequency different of daily LOGGER.info("Computing valuation of " + container.name + " with frequency " + frequency.name) start_date = datetime.date(2014,1,1) if container.inception_date==None else container.inception_date today = datetime.date.today() valuation = {} all_positions = get_positions_portfolio(container) all_positions = all_positions['data'] if all_positions!=None else {} previous_key = None previous_date = None while start_date<today: work_date = get_work_date(start_date, frequency) key_date = str(epoch_time(work_date)) period_duration = float(get_current_period_duration(work_date, frequency)) period_position = float(get_current_date_position(start_date, frequency)) if not valuation.has_key(key_date): valuation[key_date] = {'total': {'portfolio': 0.0}, 'forward': {}, 'forward_pf': 0.0,'cash': {}, 'cash_pf': 0.0, 'spot_pf': {}, 'invested': {}, 'invested_fop':{}, 'pnl': {'portfolio': 0.0}, 'fx_pnl': {}, 'movement':{'portfolio': 0.0, 'portfolio_tw': 0.0}, 'performances': {'mdietz': {'day': 0.0, 'wtd': 0.0, 'mtd': 0.0, 'qtd': 0.0, 'std': 0.0, 'ytd': 0.0, 'si': 0.0}}} else: valuation[key_date]['cash'] = {} valuation[key_date]['forward'] = {} valuation[key_date]['cash_pf'] = 0.0 valuation[key_date]['forward_pf'] = 0.0 valuation[key_date]['spot_pf'] = {} valuation[key_date]['invested'] = {} valuation[key_date]['total'] = {} for account in container.accounts.filter(~Q(account_type__identifier='ACC_SECURITY')): history = get_account_history(account) if history!=None: history = history['data'] if not valuation[key_date]['pnl'].has_key(account.currency.short_name): valuation[key_date]['pnl'][account.currency.short_name] = 0.0 if not valuation[key_date]['movement'].has_key(account.currency.short_name): valuation[key_date]['movement'][account.currency.short_name] = 0.0 if history!=None: value = valuation_content.get_closest_value(history, dt.combine(start_date, dt.min.time()), True) if account.account_type.identifier=='ACC_CURRENT': account_key = 'cash' elif account.account_type.identifier=='ACC_FORWARD': account_key = 'forward' if not valuation[key_date][account_key].has_key(account.currency.short_name): valuation[key_date][account_key][account.currency.short_name] = {'portfolio': 0.0, 'account': 0.0} if not valuation[key_date]['movement'].has_key(account.currency.short_name): valuation[key_date]['movement'][account.currency.short_name] = 0.0 if value!=None: valuation[key_date][account_key][account.currency.short_name]['account'] += value['assets'] if not valuation[key_date]['total'].has_key(account.currency.short_name): valuation[key_date]['total'][account.currency.short_name] = 0.0 valuation[key_date]['total'][account.currency.short_name] += value['assets'] valuation[key_date][account_key][account.currency.short_name]['portfolio'] += value['assets_pf'] valuation[key_date][account_key + '_pf'] += value['assets_pf'] valuation[key_date]['spot_pf'][account.currency.short_name] = value['spot_pf'] valuation[key_date]['movement'][account.currency.short_name] += value['mvt_no_pnl'] valuation[key_date]['movement']['portfolio'] += value['mvt_no_pnl_pf'] valuation[key_date]['movement']['portfolio_tw'] += value['mvt_no_pnl_pf'] * ((period_duration - period_position + 1.0)/period_duration) valuation[key_date]['pnl'][account.currency.short_name] += value['mvt_pnl'] valuation[key_date]['pnl']['portfolio'] += value['mvt_pnl_pf'] if not valuation[key_date]['invested'].has_key('portfolio'): valuation[key_date]['invested']['portfolio'] = 0.0 if not valuation[key_date]['invested_fop'].has_key('portfolio'): valuation[key_date]['invested_fop']['portfolio'] = 0.0 current_positions = valuation_content.get_closest_value(all_positions, work_date, True) if current_positions!=None: for position in current_positions: if position not in ['increase', 'decrease', 'increase_fop', 'decrease_fop']: LOGGER.info("Operation on security with id [" + str(position) + "]") security = SecurityContainer.objects.get(id=position) divisor = get_price_divisor(security) amount = current_positions[position]['total'] * current_positions[position]['price'] / divisor amount_portfolio = current_positions[position]['total'] * current_positions[position]['price_pf'] / divisor if not valuation[key_date]['invested'].has_key(security.currency.short_name): valuation[key_date]['invested'][security.currency.short_name] = 0.0 valuation[key_date]['invested'][security.currency.short_name] += amount valuation[key_date]['invested']['portfolio'] += amount_portfolio elif position in ['increase_fop', 'decrease_fop']: valuation[key_date]['invested_fop']['portfolio'] += (current_positions[position]['portfolio'] * (1.0 if position=='increase_fop' else -1.0)) valuation[key_date]['total']['portfolio'] = valuation[key_date]['cash_pf'] + valuation[key_date]['invested']['portfolio'] new_work_date = get_work_date(dates.AddDay(start_date, 1), frequency) new_key_date = str(epoch_time(new_work_date)) # Modified dietz if key_date!=new_key_date or dates.AddDay(start_date, 1)>=today: if previous_key!=None: movement_previous_spot = 0.0 for key_currency in valuation[key_date]['movement'].keys(): if key_currency!='portfolio' and key_currency!='portfolio_tw' and valuation[key_date]['movement'][key_currency]!=0.0: movement_previous_spot += valuation[key_date]['movement'][key_currency] * (valuation[previous_key]['spot_pf'][key_currency] if valuation[previous_key]['spot_pf'].has_key(key_currency) else valuation[key_date]['spot_pf'][key_currency]) else: movement_previous_spot = valuation[key_date]['movement']['portfolio'] mdietz_up = valuation[key_date]['total']['portfolio'] - valuation[key_date]['invested_fop']['portfolio'] - (valuation[previous_key]['total']['portfolio'] if previous_key!=None else 0.0) - movement_previous_spot mdietz_down = (valuation[previous_key]['total']['portfolio'] if previous_key!=None else 0.0) + valuation[key_date]['movement']['portfolio_tw'] if mdietz_down!=0.0: mdietz = mdietz_up / mdietz_down else: mdietz = 0.0 # First is used to determine if this is the reference frequency that is computed first = True for key_perf in PERF_MAPPING[frequency.identifier]: if first: valuation[key_date]['performances']['mdietz'][key_perf] = mdietz * 100.0 else: if previous_date!=None: if key_perf=='si' or (previous_key!=key_date and get_work_date(previous_date, DATE_MAPPING[key_perf])==get_work_date(start_date, DATE_MAPPING[key_perf])): valuation[key_date]['performances']['mdietz'][key_perf] = (((valuation[previous_key]['performances']['mdietz'][key_perf]/100.0 + 1.0) * (mdietz + 1.0)) - 1.0) * 100.0 elif get_work_date(previous_date, DATE_MAPPING[key_perf])!=get_work_date(start_date, DATE_MAPPING[key_perf]): valuation[key_date]['performances']['mdietz'][key_perf] = mdietz * 100.0 else: valuation[key_date]['performances']['mdietz'][key_perf] = mdietz * 100.0 first = False if key_date!=new_key_date: previous_key = key_date previous_date = start_date start_date = dates.AddDay(start_date, 1) set_portfolios_valuation({str(container.id): valuation}) for wrk_frequency in DATE_MAPPING.values(): self.generate_tracks(container, wrk_frequency, valuation)