Esempio n. 1
0
def getOtherAssetType(blpData, position):
    """
	For Fixed Income or Equity asset type, use Bloomberg "MARKET_SECTOR_DES" 
	field to lookup:

	If the field is "Equity", then asset class = "Equity", sub category
	"Listed Equity" if Bloomberg field "EXCH_MARKET_STATUS" = "ACTV", else
	sub category "Unlisted Equity".

	If the field is "Comdty", then asset type = ('Commodity', 'Derivatives')

	Otherwise its Bloomberg field "CAPITAL_CONTINGENT_SECURITY" 
	= "Y", then asset class is:

	('Fixed Income', 'Additional Tier 1, Contingent Convertibles')

	Else use the below mapping

	Corp -> Fixed Income, sub catetory "Corporate Bond"
	Govt -> Fixed Income, sub catetory "Government Bond"
	"""
    isEquityType = lambda blpData, position: \
     blpData[getIdnType(position)[0]]['MARKET_SECTOR_DES'] == 'Equity'


    isCommodityType = lambda blpData, position: \
     blpData[getIdnType(position)[0]]['MARKET_SECTOR_DES'] == 'Comdty'


    isFIType = lambda blpData, position: \
     blpData[getIdnType(position)[0]]['MARKET_SECTOR_DES'] in ['Corp', 'Govt']


    isCapitalContingentSecurity = lambda blpData, position: \
     blpData[getIdnType(position)[0]]['CAPITAL_CONTINGENT_SECURITY'] == 'Y'

    # FIXME: this function is not complete, as index futures are not included
    getEquityAssetType = lambda blpData, position: \
     ('Equity', 'Listed Equities') if blpData[getIdnType(position)[0]]['EXCH_MARKET_STATUS'] == 'ACTV' \
     else ('Equity', 'Unlisted Equities')

    # FIXME: this function is not complete, as physical commodity is not included
    # getCommodityAssetType = lambda blpData, position: \
    # 	('Commodity', 'Derivatives')


    getFIAssetType = lambda blpData, position: \
     ('Fixed Income', 'Additional Tier 1, Contingent Convertibles') \
     if isCapitalContingentSecurity(blpData, position) else \
     ('Fixed Income', 'Corporate') if blpData[getIdnType(position)[0]]['MARKET_SECTOR_DES'] == 'Corp' else \
     ('Fixed Income', 'Government') if blpData[getIdnType(position)[0]]['MARKET_SECTOR_DES'] == 'Govt' else \
     lognRaise('getFIAssetType(): unsupported FI type {0}'.format(getIdnType(position)))


    return \
    getEquityAssetType(blpData, position) if isEquityType(blpData, position) else \
    getCommodityAssetType(blpData, position) if isCommodityType(blpData, position) else \
    getFIAssetType(blpData, position) if isFIType(blpData, position) else \
    lognRaise('getOtherAssetType(): invalid asset type: {0}'.format(getIdnType(position)))
Esempio n. 2
0
def getOthersCountry(blpData, position):
    """
	[Dictionary] blpData, [Dictionary] position => [String] country

	The logic to deal with commodity product is not yet clear, so we put it
	here.
	"""
    _id, _id_type = getIdnType(position)
    if (_id, _id_type) == ('TYM1 Comdty', 'TICKER'):
        return 'US'
    else:
        # FIXME: Add implementation
        lognRaise('getCommodityCountry(): {0}'.format(getIdnType(position)))
Esempio n. 3
0
def getFundCountry(blpData, position):
    """
	[Dictionary] blpData, [Dictionary] position => [String] country

	The logic to deal with fund, no matter listed fund (ETF) or open ended fund,
	is not yet clear, so we put it here.
	"""
    # FIXME: Need a formal implementation, now just case by case
    fundCountry = {}

    try:
        return fundCountry[getIdnType(position)[0]]
    except KeyError:
        lognRaise('getFundCountry(): {0}'.format(getIdnType(position)))
Esempio n. 4
0
 def verifyBlpPosition(self, p):
     self.assertEqual('20200131', getPositionDate(p))
     self.assertEqual('12734', getPortfolioId(p))
     self.assertEqual('USD', getBookCurrency(p))
     self.assertEqual(('USF2R125CE38', 'ISIN'), getIdnType(p))
     self.assertEqual(11698622.22, getMarketValue(p))
     self.assertEqual(11000000, getQuantity(p))
Esempio n. 5
0
 def verifyInvestmentPosition(self, p):
     self.assertEqual('20200429', getPositionDate(p))
     self.assertEqual('19437', getPortfolioId(p))
     self.assertEqual('HKD', getBookCurrency(p))
     self.assertEqual(('1299 HK Equity', 'TICKER'), getIdnType(p))
     self.assertEqual(12749540, getMarketValue(p))
     self.assertEqual(177200, getQuantity(p))
Esempio n. 6
0
def getCommodityCountry(blpData, position):
    """
	[Dictionary] blpData, [Dictionary] position => [String] country

	The logic to deal with commodity product is not yet clear, so we put it
	here.
	"""
    # FIXME: not implemented
    lognRaise('getCommodityCountry(): {0}'.format(getIdnType(position)))
Esempio n. 7
0
def getMoneyMarketCountry(position):
    """
	[Dictionary] position => [String] country

	A money market product can be an OTC product, for example, a fixed deposit,
	so we deal with them here.
	"""
    # FIXME: Assume all money market instruments are made in Hong Kong
    return lognContinue(
        'getMoneyMarketCountry(): {0}'.format(getIdnType(position)), 'HK')
Esempio n. 8
0
def getPrivateSecurityCountry(position):
    """
	[Dictionary] position => [String] country

	A private security is a non-listed security, non-listed fund or others
	that cannot find their information through Bloomberg. So we deal with them
	here.
	"""
    # FIXME: Add implementation
    lognRaise('getPrivateSecurityCountry(): {0}'.format(getIdnType(position)))
Esempio n. 9
0
def getAverageRatingScoreSpecialCase(position):
    """
	[Dictionary] position => [Float] score

	When none of the rating agencies gives a credit rating, we provide the 
	ratings here.

	The current implementation gives a rating score of 0 in such case.
	"""
    logger.warning('getAverageRatingScoreSpecialCase(): {0}'.format(
        getIdnType(position)))
    return 0
Esempio n. 10
0
def isSpecialCase(position):
    """
	[Dictionary] position => [Bool] is this a special case in asset type,
								private security, open ended fund or something
								that needs override.
	"""
    portfolioMatched = lambda p1, p2: True if p2 == '' or p1 == p2 else False

    return compose(
        lambda t: t[0] in t[2] and portfolioMatched(t[1], t[2][t[0]][
            'Portfolio']), lambda position:
        (getIdnType(position)[0], getPortfolioId(position),
         getAssetTypeSpecialCaseData()))(position)
Esempio n. 11
0
def getAssetType(blpData, position):
    """
	[Dictionary] position (a Geneva or Blp position)
		=> [Tuple] asset type

	The asset type is a tuple containing the category and sub category, like
	('Cash', ), ('Fixed Income', 'Corporate') or ('Equity', 'Listed')
	"""
    logger.debug('getAssetType(): {0}'.format(getIdnType(position)))

    return \
    getSpecialCaseAssetType(position) if isSpecialCase(position) else \
    getPrivateSecurityAssetType(position) if isPrivateSecurity(position) else \
    ('Cash', ) if isCash(position) else \
    ('Foreign Exchange Derivatives', ) if isFxForward(position) else \
    ('Fixed Income', 'Cash Equivalents') if isMoneyMarket(position) else \
    getRepoAssetType(position) if isRepo(position) else \
    getFundAssetType(position) if isFund(position) else \
    getOtherAssetType(blpData, position)
Esempio n. 12
0
def getAverageRatingScore(blpData,
                          position,
                          specialCaseHandler=getAverageRatingScoreSpecialCase):
    """
	[Dictionary] blpData, [Dictionary] position
		=> [Float] score
	"""
    logger.debug('getAverageRatingScore(): {0}'.format(getIdnType(position)))

    averageScore = lambda position, scores: \
     specialCaseHandler(position) if len(scores) == 0 else \
     scores[0] if len(scores) == 1 else \
     min(scores) if len(scores) == 2 else \
     sorted(scores)[1]


    return \
    compose(
     partial(averageScore, position)
      , lambda scores: list(filterfalse(lambda x: x == 0, scores))
      , getRatingScores
    )(blpData, position)
Esempio n. 13
0
def getGenevaLqaPositions(positions):
	"""
	[Iterable] positions => [Iterable] positions

	Read Geneva consolidated tax lot positions, then do the following: 

	1) take out those not suitable for liquidity test (cash, FX forward, etc.);
	2) Add Id, IdType and Position fields for LQA processing.

	"""

	# [Dictonary] p => [Dictionary] enriched position with id and idType
	addIdnType = compose(
		lambda t: mergeDict(t[2], {'Id': t[0], 'IdType': t[1]})
	  , lambda p: (*getIdnType(p), p)
	)


	return compose(
		partial(map, addIdnType)
	  , partial(filterfalse, noNeedLiquidityGeneva)
	  , lambda positions: lognContinue('getGenevaLqaPositions(): start', positions)
	)(positions)
Esempio n. 14
0
def getCountryCode(blpData, position):
    """
	[Dictionary] blpInfo, [Dictionary] position => [String] country code
	"""
    logger.debug('getCountryCode(): {0}'.format(getIdnType(position)))

    isCommodityType = lambda blpData, position: \
     getAssetType(blpData, position)[0] == 'Commodity'


    isFundType = lambda blpData, position: \
     getAssetType(blpData, position)[0] == 'Fund'


    isEquityType = lambda blpData, position: \
     getAssetType(blpData, position)[0] == 'Equity'


    isFIType = lambda blpData, position: \
     getAssetType(blpData, position)[0] == 'Fixed Income'


    isOthersType = lambda blpData, position: \
     getAssetType(blpData, position)[0] == 'Others'


    return \
    getSpecialCaseCountry(position) if isSpecialCase(position) else \
    getPrivateSecurityCountry(position) if isPrivateSecurity(position) else \
    getRepoCountry(position) if isRepo(position) else \
    getMoneyMarketCountry(position) if isMoneyMarket(position) else \
    getCommodityCountry(blpData, position) if isCommodityType(blpData, position) else \
    getFundCountry(blpData, position) if isFundType(blpData, position) else \
    getOthersCountry(blpData, position) if isOthersType(blpData, position) else \
    getEquityCountry(blpData, position) if isEquityType(blpData, position) else \
    getFICountry(blpData, position) if isFIType(blpData, position) else \
    lognRaise('getCountryCode(): unsupported asset type')
Esempio n. 15
0
def getBlpLqaPositions(positions):
	"""
	[Iterable] positions => ( [Iterable] CLO positions
					 	    , [Iterable] nonCLO positions
					 	    )

	Read Bloomberg raw positions, then do the following: 

	1) take out those not suitable to do liquidity test (cash, FX forward, etc.);
	2) take out DIF fund positions, since they will come from Geneva;
	2) split into clo and nonCLO positions.

	Return (CLO positions, nonCLO positions)
	"""
	removeUnwantedPositions = compose(
		partial( filterfalse
	  		   , lambda p: p['Asset Type'] in [ 'Cash', 'Foreign Exchange Forward'
	  		   								  , 'Repo Liability', 'Money Market'] \
					or p['Name'] in ['.FSFUND HK', 'CLFLDIF HK']	# open ended funds
			   )
	  
	  , partial(filterfalse, lambda p: p['Position'] == '' or p['Position'] <= 0)
	)


	# [Dictionary] position => [Dictioanry] position with id and idtype
	updatePositionId = compose(
		lambda t: mergeDict(t[2], {'Id': t[0], 'IdType': t[1]})
	  , lambda position: (*getIdnType(position), position)
	)


	isCLOPortfolio = lambda p: p['Account Code'] in \
						['12229', '12734', '12366', '12630', '12549', '12550', '13007']


	"""
	[Iterable] positions => ( [Iterable] CLO positions
							, [Iterable] non CLO positions
							)

	Split the positions into All, CLO and non-CLO group
	"""
	splitCLO = lambda positions: \
		reduce( lambda acc, el: ( chain(acc[0], [el])
								, acc[1]
								) if isCLOPortfolio(el) else \
								
								( acc[0]
								, chain(acc[1], [el])
								)
	  		  , positions
	  		  , ([], [])
	  		  )


	return \
	compose(
		splitCLO
	  , partial(map, updatePositionId)
	  , removeUnwantedPositions		
	  , lambda positions: lognContinue('getBlpLqaPositions(): start', positions)
	)(positions)
Esempio n. 16
0

def getPrivateSecurityAssetType(position):
    """
	[Dictionary] position => [Tuple] Asset Type

	Handle special cases for private securities
	"""
    # FIXME: add implementation
    logger.debug('getPrivateSecurityAssetType()')
    raise ValueError


""" [Dictionary] position => [Tuple] asset type """
getSpecialCaseAssetType = lambda position: \
 getAssetTypeSpecialCaseData()[getIdnType(position)[0]]['AssetType']
""" [Dictionary] position => [String] country """
getSpecialCaseCountry = lambda position: \
 getAssetTypeSpecialCaseData()[getIdnType(position)[0]]['CountryCode']


def isSpecialCase(position):
    """
	[Dictionary] position => [Bool] is this a special case in asset type,
								private security, open ended fund or something
								that needs override.
	"""
    portfolioMatched = lambda p1, p2: True if p2 == '' or p1 == p2 else False

    return compose(
        lambda t: t[0] in t[2] and portfolioMatched(t[1], t[2][t[0]][
Esempio n. 17
0
def getEquityCountry(blpData, position):
    """
	[Dictionary] blpData, [Dictionary] position => [String] country
	"""
    logger.debug('getEquityCountry()')
    return blpData[getIdnType(position)[0]]['CNTRY_ISSUE_ISO']
Esempio n. 18
0
def getFICountry(blpData, position):
    """
	[Dictionary] blpData, [Dictionary] position => [String] country
	"""
    logger.debug('getFICountry()')
    return blpData[getIdnType(position)[0]]['CNTRY_OF_RISK']