Coverage for src/scrilla/static/formats.py: 93%

71 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-07-18 18:14 +0000

1import argparse 

2 

3from scrilla.static import constants, definitions 

4from scrilla.util.helper import significant_digits, exceeds_accuracy 

5 

6formats = { 

7 'separator': '-', 

8 'TAB': ' ', 

9 'LINE_LENGTH': 100, 

10 'BAR_WIDTH': 0.10, 

11 'INDENT': 10, 

12 'RISK_FREE_TITLE': "{} US Treasury", 

13 'BINS': 20 

14} 

15 

16 

17def format_float_number(decimal: float) -> str: 

18 if exceeds_accuracy(decimal): 

19 return '0' 

20 accuracy = f'.{constants.constants["ACCURACY"]}f' 

21 sigfigs = format(significant_digits( 

22 decimal, constants.constants["SIG_FIGS"]), accuracy) 

23 return sigfigs.rstrip('0').rstrip('.') 

24 

25 

26def format_float_percent(decimal: float) -> str: 

27 if exceeds_accuracy(decimal): 

28 return "0%" 

29 accuracy = f'.{constants.constants["ACCURACY"]}f' 

30 sigfigs = format(100*significant_digits(decimal, 

31 constants.constants['SIG_FIGS']), accuracy) 

32 return sigfigs.rstrip('0').rstrip('.') + '%' 

33 

34 

35def format_dict_percent(this_dict: dict, which_key: str) -> dict: 

36 buffer_dict = this_dict.copy() 

37 buffer_dict[which_key] = format_float_percent(this_dict[which_key]) 

38 return buffer_dict 

39 

40 

41def format_dict_number(this_dict: dict, which_key: str) -> dict: 

42 buffer_dict = this_dict.copy() 

43 buffer_dict[which_key] = format_float_number(this_dict[which_key]) 

44 return buffer_dict 

45 

46 

47def format_allocation(allocation, portfolio, investment=None, latest_prices=None): 

48 allocation_format = [] 

49 

50 if investment is not None: 50 ↛ 51line 50 didn't jump to line 51, because the condition on line 50 was never true

51 shares = portfolio.calculate_approximate_shares( 

52 x=allocation, total=investment, latest_prices=latest_prices) 

53 total = portfolio.calculate_actual_total( 

54 x=allocation, total=investment, latest_prices=latest_prices) 

55 

56 annual_volatility = portfolio.volatility_function(x=allocation) 

57 annual_return = portfolio.return_function(x=allocation) 

58 

59 for j, item in enumerate(portfolio.tickers): 

60 holding = {'ticker': item, 'allocation': round(allocation[j], constants.constants['ACCURACY']), 'annual_return': round( 

61 portfolio.mean_return[j], constants.constants['ACCURACY']), 'annual_volatility': round( 

62 portfolio.sample_vol[j], constants.constants['ACCURACY'])} 

63 if investment is not None: 63 ↛ 64line 63 didn't jump to line 64, because the condition on line 63 was never true

64 holding['shares'] = float(shares[j]) 

65 allocation_format.append(holding) 

66 

67 json_format = {'holdings': allocation_format, 

68 'portfolio_return': annual_return, 'portfolio_volatility': annual_volatility} 

69 

70 if investment is not None: 70 ↛ 71line 70 didn't jump to line 71, because the condition on line 70 was never true

71 json_format['total'] = float(total) 

72 

73 return json_format 

74 

75 

76def format_frontier(portfolio, frontier, investment=None, latest_prices=None): 

77 json_format = [] 

78 for item in frontier: 

79 json_format.append(format_allocation(allocation=item, portfolio=portfolio, 

80 investment=investment, latest_prices=latest_prices)) 

81 return json_format 

82 

83 

84def format_correlation_matrix(tickers, correlation_matrix): 

85 response = [] 

86 for i in range(0, len(tickers)-1): 

87 subresponse = {} 

88 for j in range(i+1, len(tickers)): 

89 subresponse[f'{tickers[i]}_{tickers[j]}_correlation'] = correlation_matrix[j][i] 

90 response.append(subresponse) 

91 return response 

92 

93 

94def format_args(args, default_estimation_method) -> argparse.Namespace: 

95 parser = argparse.ArgumentParser() 

96 

97 choices = [] 

98 for func in definitions.FUNC_DICT: 

99 choices.append(definitions.FUNC_DICT[func]['values'][0]) 

100 choices.append(definitions.FUNC_DICT[func]['values'][1]) 

101 

102 parser.add_argument('function_arg', choices=choices) 

103 

104 groups = [parser.add_mutually_exclusive_group() 

105 for _ in definitions.ARG_META_DICT['groups']] 

106 

107 for arg in definitions.ARG_DICT: 

108 if definitions.ARG_DICT[arg]['format'] not in ('group', bool): 

109 parser.add_argument(definitions.ARG_DICT[arg]['values'][0], 

110 definitions.ARG_DICT[arg]['values'][1], 

111 definitions.ARG_DICT[arg]['values'][2], 

112 definitions.ARG_DICT[arg]['values'][3], 

113 default=None, 

114 type=definitions.ARG_DICT[arg]['format'], 

115 dest=arg) 

116 elif definitions.ARG_DICT[arg]['format'] == 'group': 

117 group_index = definitions.ARG_META_DICT['groups'].index( 

118 definitions.ARG_DICT[arg]['group']) 

119 groups[group_index].add_argument(definitions.ARG_DICT[arg]['values'][0], 

120 definitions.ARG_DICT[arg]['values'][1], 

121 definitions.ARG_DICT[arg]['values'][2], 

122 definitions.ARG_DICT[arg]['values'][3], 

123 action='store_const', 

124 dest=definitions.ARG_DICT[arg]['group'], 

125 const=arg) 

126 # NOTE: 'format' == group AND 'format' == bool => Empty Set, so only other alternative is 

127 # 'format' == bool 

128 else: 

129 parser.add_argument(definitions.ARG_DICT[arg]['values'][0], 

130 definitions.ARG_DICT[arg]['values'][1], 

131 definitions.ARG_DICT[arg]['values'][2], 

132 definitions.ARG_DICT[arg]['values'][3], 

133 action='store_true', 

134 dest=arg) 

135 

136 parser.set_defaults(estimation_method=default_estimation_method) 

137 parser.add_argument('tickers', nargs='*', type=str) 

138 return vars(parser.parse_args(args))