DYPMS 0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
DYPMS/__init__.py ADDED
@@ -0,0 +1,27 @@
1
+ from .client import Client
2
+
3
+ __all__ = ['Client']
4
+
5
+
6
+ def get_simulate_portfolio_list(*args, **kwargs):
7
+ return Client.get_instance().get_simulate_portfolio_list(*args, **kwargs)
8
+
9
+
10
+ def get_simulate_portfolio_position(*args, **kwargs):
11
+ return Client.get_instance().get_simulate_portfolio_position(*args, **kwargs)
12
+
13
+
14
+ def get_simulate_portfolio_position_hierarchy(*args, **kwargs):
15
+ return Client.get_instance().get_simulate_portfolio_position_hierarchy(*args, **kwargs)
16
+
17
+
18
+ def get_simulate_portfolio_performance_indicators(*args, **kwargs):
19
+ return Client.get_instance().get_simulate_portfolio_performance_indicators(*args, **kwargs)
20
+
21
+
22
+ def get_simulate_portfolio_net(*args, **kwargs):
23
+ return Client.get_instance().get_simulate_portfolio_net(*args, **kwargs)
24
+
25
+
26
+ def get_style_attr_trend(*args, **kwargs):
27
+ return Client.get_instance().get_style_attr_trend(*args, **kwargs)
DYPMS/api/__init__.py ADDED
File without changes
@@ -0,0 +1,41 @@
1
+ import requests
2
+ import pandas as pd
3
+ from .util import get_response_json_with_check
4
+
5
+ field_mapping = {
6
+ 'accountName': 'simulate_portfolio_name', # 产品名称
7
+ 'accountCode': 'simulate_portfolio_id', # 产品代码
8
+ 'openDate': 'establishment_date', # 成立日期
9
+ 'category': 'product_type', # 账户类型作为产品类型
10
+ 'reportingBenchmark': 'benchmark', # 参考基准
11
+ 'user': 'creator', # 用户作为创建人
12
+ 'netValueStartDate': 'NAV_start_date', # 净值开始日期
13
+ 'netValueDate': 'latest_NAV_date', # 最新净值日期
14
+ 'navFrequency': 'NAV_update_frequency' # 净值更新频率
15
+ }
16
+
17
+
18
+ def get_simulate_portfolio_list(client,
19
+ simulate_portfolio_id=None):
20
+
21
+ url = f"{client.base_url}/lib/simulate/portfolio/v1/list"
22
+ headers = client.get_headers()
23
+ data = "[]"
24
+ if simulate_portfolio_id:
25
+ data = "[\"" + simulate_portfolio_id + "\"]"
26
+
27
+ try:
28
+ response = requests.post(url, headers=headers, data=data)
29
+ r = get_response_json_with_check(response)
30
+
31
+ rows = []
32
+ for item in r.get('list'):
33
+ row = {}
34
+ for api_field, our_field in field_mapping.items():
35
+ row[our_field] = item.get(api_field, None)
36
+ rows.append(row)
37
+
38
+ df = pd.DataFrame(rows)
39
+ return df
40
+ except Exception as e:
41
+ raise e
@@ -0,0 +1,48 @@
1
+ import requests
2
+ import pandas as pd
3
+ from .util import get_response_json_with_check
4
+
5
+ field_mapping = {
6
+ 'date': '净值日期',
7
+ 'unitNav': '单位净值',
8
+ 'accumNav': '累计净值',
9
+ 'adjustNav': '复权净值'
10
+ }
11
+
12
+
13
+ def get_simulate_portfolio_net(client,
14
+ simulate_portfolio_id,
15
+ start_date,
16
+ end_date):
17
+ """
18
+ 查询模拟组合净值
19
+
20
+ Args:
21
+ client: DYPMS客户端实例
22
+ simulate_portfolio_id: 模拟组合代码,必传
23
+ start_date: 开始日期,必传
24
+ end_date: 结束日期,必传
25
+ """
26
+ url = f"{client.base_url}/lib/simulate/portfolio/v1/nav"
27
+ headers = client.get_headers()
28
+ params = {
29
+ 'accountCode': simulate_portfolio_id,
30
+ 'startDate': start_date,
31
+ 'endDate': end_date
32
+ }
33
+
34
+ try:
35
+ response = requests.get(url, headers=headers, params=params)
36
+ r = get_response_json_with_check(response)
37
+
38
+ rows = []
39
+ for item in r.get('list'):
40
+ row = {}
41
+ for api_field, our_field in field_mapping.items():
42
+ row[our_field] = item.get(api_field, None)
43
+ rows.append(row)
44
+
45
+ df = pd.DataFrame(rows)
46
+ return df
47
+ except Exception as e:
48
+ raise e
@@ -0,0 +1,58 @@
1
+ import requests
2
+ import pandas as pd
3
+ from .util import get_response_json_with_check
4
+
5
+ field_mapping = {
6
+ 'accountCode': 'simulate_portfolio_id',
7
+ 'benchmark': 'benchmark',
8
+ 'startDate': 'start_date',
9
+ 'endDate': 'end_date',
10
+ 'totalReturn': 'cumulative_return',
11
+ 'activeReturn': 'active_return',
12
+ 'latestWeekReturn': 'recent_week_return',
13
+ 'thisWeekReturn': 'weekly_return',
14
+ 'latestMonthReturn': 'recent_month_return',
15
+ 'thisMonthReturn': 'monthly_return',
16
+ 'ytdReturn': 'YTD_return',
17
+ 'annualTotalReturn': 'annualized_total_return',
18
+ 'annualActiveReturn': 'annualized_active_return',
19
+ 'annualTotalRisk': 'annualized_total_risk',
20
+ 'annualActiveRisk': 'annualized_active_risk',
21
+ 'maxDrawdown': 'maximum_drawdown',
22
+ 'sharpRatio': 'sharpe_ratio',
23
+ 'infoRatio': 'information_ratio',
24
+ 'sortinoRatio': 'sortino_ratio',
25
+ 'calmarRatio': 'calmar_ratio'
26
+ }
27
+
28
+
29
+ def get_simulate_portfolio_performance_indicators(client,
30
+ simulate_portfolio_id):
31
+ """
32
+ 查询模拟组合业绩指标
33
+
34
+ Args:
35
+ client: DYPMS客户端实例
36
+ simulate_portfolio_id: 模拟组合代码,必传
37
+ """
38
+ url = f"{client.base_url}/lib/simulate/portfolio/v1/perf"
39
+ headers = client.get_headers()
40
+ params = {'accountCode': simulate_portfolio_id}
41
+
42
+ try:
43
+ response = requests.get(url, headers=headers, params=params)
44
+ r = get_response_json_with_check(response)
45
+
46
+ # 转换单个对象为DataFrame
47
+ data = r.get('data')
48
+ if data:
49
+ row = {}
50
+ for api_field, our_field in field_mapping.items():
51
+ row[our_field] = data.get(api_field, None)
52
+ df = pd.DataFrame([row])
53
+ else:
54
+ df = pd.DataFrame()
55
+
56
+ return df
57
+ except Exception as e:
58
+ raise e
@@ -0,0 +1,169 @@
1
+ import requests
2
+ import pandas as pd
3
+ from .util import get_response_json_with_check
4
+ from ..enums import PenetrateType, PositionField
5
+
6
+ default_fields = [
7
+ 'assetCategory',
8
+ 'date',
9
+ 'assetName',
10
+ 'assetCode',
11
+ 'securityType',
12
+ 'exchangeCd',
13
+ 'netPrice',
14
+ 'aiRate',
15
+ 'chg',
16
+ 'amount',
17
+ 'marketValueLocal',
18
+ 'weight',
19
+ 'dailyProfitValueLocal',
20
+ 'dailyProfitRate',
21
+ 'floatingProfitValueLocal',
22
+ 'floatingProfitRate',
23
+ 'cumulativeProfitValueLocal',
24
+ 'cumulativeProfitRate',
25
+ 'totalBuyCostLocal',
26
+ 'realizedAiLocal',
27
+ 'realizedProfitValueLocal',
28
+ 'channel',
29
+ 'positionTime'
30
+ ]
31
+
32
+ field_enum_mapping = {
33
+ PositionField.CLASS: 'assetCategory',
34
+ PositionField.DATE: 'date',
35
+ PositionField.ASSET_NAME: 'assetName',
36
+ PositionField.ASSET_CODE: 'assetCode',
37
+ PositionField.SECURITY_TYPE: 'securityType',
38
+ PositionField.TRADING_MARKET: 'exchangeCd',
39
+ PositionField.CURRENT_CLEAN_PRICE: 'netPrice',
40
+ PositionField.ACCRUED_INTEREST: 'aiRate',
41
+ PositionField.PRICE_CHANGE: 'chg',
42
+ PositionField.POSITION_QUANTITY: 'amount',
43
+ PositionField.POSITION_MARKET_VALUE: 'marketValueLocal',
44
+ PositionField.POSITION_WEIGHT_NET_ASSETS: 'weight',
45
+ PositionField.DAILY_PROFIT_LOSS: 'dailyProfitValueLocal',
46
+ PositionField.DAILY_PROFIT_LOSS_RATE: 'dailyProfitRate',
47
+ PositionField.FLOATING_PROFIT_LOSS: 'floatingProfitValueLocal',
48
+ PositionField.FLOATING_PROFIT_LOSS_RATE: 'floatingProfitRate',
49
+ PositionField.CUMULATIVE_PROFIT_LOSS: 'cumulativeProfitValueLocal',
50
+ PositionField.CUMULATIVE_PROFIT_LOSS_RATE: 'cumulativeProfitRate',
51
+ PositionField.POSITION_COST: 'totalBuyCostLocal',
52
+ PositionField.INTEREST_INCOME: 'realizedAiLocal',
53
+ PositionField.REALIZED_PROFIT_LOSS: 'realizedProfitValueLocal',
54
+ PositionField.MATURITY_DATE: 'dueDate',
55
+ PositionField.TRADING_CHANNEL: 'channel',
56
+ PositionField.POSITION_DIRECTION: 'direction',
57
+ PositionField.LATEST_PRICE: 'price',
58
+ PositionField.POSITION_WEIGHT_TOTAL_ASSETS: 'weightTotal',
59
+ PositionField.POSITION_WEIGHT_TOTAL_COST: 'weightCost',
60
+ PositionField.COST_PRICE: 'buyCost',
61
+ PositionField.AMORTIZED_COST: 'cost',
62
+ PositionField.VALUATION_EXCHANGE_RATE: 'fxRate',
63
+ PositionField.MARKET_QUOTATION_TIME: 'positionTime',
64
+ PositionField.POSITION_BUILDING_DATE: 'holdDate',
65
+ PositionField.ISSUING_ENTITY: 'partyFullName',
66
+ PositionField.REMAINING_MATURITY: 'yearToMaturity',
67
+ PositionField.BOND_RATING_AGENCY: 'nominalRatingInst',
68
+ PositionField.BOND_RATING: 'nominalRating',
69
+ PositionField.MARGIN_REQUIREMENT: 'margin',
70
+ PositionField.CITY: 'city',
71
+ PositionField.PROVINCE: 'province',
72
+ PositionField.ISSUER_RATING_YY: 'instRatingYY',
73
+ PositionField.ISSUER_RATING_DATE: 'instRatingDate',
74
+ PositionField.ISSUER_RATING: 'instRating',
75
+ PositionField.BOND_RATING_DATE: 'nominalRatingDate',
76
+ PositionField.ISSUER_RATING_AGENCY: 'instRatingInst'
77
+ }
78
+
79
+ field_mapping = {
80
+ 'assetCategory': 'class',
81
+ 'date': 'date',
82
+ 'assetName': 'asset_name',
83
+ 'assetCode': 'asset_code',
84
+ 'securityType': 'security_type',
85
+ 'exchangeCd': 'trading_market',
86
+ 'netPrice': 'current_clean_price',
87
+ 'aiRate': 'accrued_interest',
88
+ 'chg': 'price_change',
89
+ 'amount': 'position_quantity',
90
+ 'marketValueLocal': 'position_market_value',
91
+ 'weight': 'position_weight_(net_assets)',
92
+ 'dailyProfitValueLocal': 'daily_profit_loss',
93
+ 'dailyProfitRate': 'daily_profit_loss_rate',
94
+ 'floatingProfitValueLocal': 'floating_profit_loss',
95
+ 'floatingProfitRate': 'floating_profit_loss_rate',
96
+ 'cumulativeProfitValueLocal': 'cumulative_profit_loss',
97
+ 'cumulativeProfitRate': 'cumulative_profit_loss_rate',
98
+ 'totalBuyCostLocal': 'position_cost',
99
+ 'realizedAiLocal': 'interest_income',
100
+ 'realizedProfitValueLocal': 'realized_profit_loss',
101
+ 'dueDate': 'maturity_date',
102
+ 'channel': 'trading_channel',
103
+ 'direction': 'position_direction',
104
+ 'price': 'latest_price',
105
+ 'weightTotal': 'position_weight_(total_assets)',
106
+ 'weightCost': 'position_weight_(total_cost)',
107
+ 'buyCost': 'cost_price',
108
+ 'cost': 'amortized_cost',
109
+ 'fxRate': 'valuation_exchange_rate',
110
+ 'positionTime': 'market_quotation_time',
111
+ 'holdDate': 'position_building_date',
112
+ 'partyFullName': 'issuing_entity',
113
+ 'yearToMaturity': 'remaining_maturity',
114
+ 'nominalRatingInst': 'bond_rating_agency',
115
+ 'nominalRating': 'bond_rating',
116
+ 'margin': 'margin_requirement',
117
+ 'city': 'city',
118
+ 'province': 'province',
119
+ 'instRatingYY': 'issuer_rating_(YY)',
120
+ 'instRatingDate': 'issuer_rating_date',
121
+ 'instRating': 'issuer_rating',
122
+ 'nominalRatingDate': 'bond_rating_date',
123
+ 'instRatingInst': 'issuer_rating_agency'
124
+ }
125
+
126
+
127
+ def get_simulate_portfolio_position(client,
128
+ simulate_portfolio_id,
129
+ start_date=None,
130
+ end_date=None,
131
+ penetrate_style=PenetrateType.NO_PENETRATE):
132
+ """
133
+ 查询模拟组合持仓
134
+
135
+ Args:
136
+ client: DYPMS客户端实例
137
+ simulate_portfolio_id: 模拟组合代码,必传
138
+ start_date: 开始日期
139
+ end_date: 结束日期
140
+ penetrate_style: 穿透方式,枚举PenetrateType
141
+ """
142
+ url = f"{client.base_url}/lib/simulate/portfolio/v1/position"
143
+ headers = client.get_headers()
144
+
145
+ data = {
146
+ 'accountCode': simulate_portfolio_id,
147
+ 'startDate': start_date,
148
+ 'endDate': end_date,
149
+ 'penetrateWay': penetrate_style.name if penetrate_style else PenetrateType.NO_PENETRATE,
150
+ }
151
+
152
+ # 移除None值
153
+ data = {k: v for k, v in data.items() if v is not None}
154
+
155
+ try:
156
+ response = requests.post(url, headers=headers, json=data)
157
+ r = get_response_json_with_check(response)
158
+
159
+ rows = []
160
+ for item in r.get('list'):
161
+ row = {}
162
+ for api_field, our_field in field_mapping.items():
163
+ row[our_field] = item.get(api_field, None)
164
+ rows.append(row)
165
+
166
+ df = pd.DataFrame(rows)
167
+ return df
168
+ except Exception as e:
169
+ raise e
@@ -0,0 +1,97 @@
1
+ import requests
2
+ import pandas as pd
3
+ from .util import get_response_json_with_check
4
+
5
+ field_mapping = {
6
+ 'symbol': 'symbol',
7
+ 'symbolName': 'symbol_name',
8
+ 'securityId': 'security_id',
9
+ 'exchangeCd': 'exchange_code',
10
+ 'channel': 'channel',
11
+ 'ticker': 'ticker',
12
+ 'mdSecurityId': 'md_security_id',
13
+ 'securityType': 'security_type',
14
+ 'positionDate': 'position_date',
15
+ 'direction': 'direction',
16
+
17
+ 'value': 'market_value',
18
+ 'positionValue': 'position_value',
19
+ 'closePrice': 'close_price',
20
+ 'amount': 'quantity',
21
+ 'canSellQuantity': 'available_sell_quantity',
22
+ 'totalBuyCost': 'total_buy_cost',
23
+ 'buyCost': 'buy_cost',
24
+ 'cost': 'holding_cost',
25
+ 'profit': 'realized_profit',
26
+ 'dailyProfitValue': 'daily_pnl_value',
27
+ 'dailyProfitRate': 'daily_pnl_rate',
28
+ 'floatingProfitValue': 'unrealized_pnl_value',
29
+ 'floatingProfitRate': 'unrealized_pnl_rate',
30
+ 'cumulativeProfitValue': 'cumulative_pnl_value',
31
+ 'cumulativeProfitRate': 'cumulative_pnl_rate',
32
+ 'cumulativeProfitRateTw': 'cumulative_pnl_rate_tw', # TW 可能指 Time-Weighted
33
+ 'weight': 'weight',
34
+ 'coveredQuantity': 'covered_quantity',
35
+ 'buyCostHke': 'buy_cost_hke',
36
+ 'costHke': 'holding_cost_hke',
37
+ 'orgBuyCost': 'original_buy_cost',
38
+ 'orgCost': 'original_holding_cost',
39
+ 'margin': 'margin',
40
+ 'dueDate': 'due_date',
41
+ 'aiRate': 'accrued_interest_rate',
42
+ 'netPrice': 'net_price',
43
+ 'positionTime': 'position_time',
44
+ 'changePct': 'price_change_pct',
45
+ 'partialWeight': 'partial_weight',
46
+ 'marginWeight': 'margin_weight',
47
+ 'netPricePnlRate': 'net_price_pnl_rate',
48
+ 'fundReportDate': 'fund_report_date',
49
+ 'includeFofPerspective': 'include_fof_perspective',
50
+ 'category1': 'category_level_1',
51
+ 'category2': 'category_level_2',
52
+ 'cumulativeDividendValue': 'cumulative_dividend_value',
53
+ 'freezeAllotCash': 'frozen_allotment_cash',
54
+ 'receivableShareAmount': 'receivable_shares',
55
+ 'receivableDividendValue': 'receivable_dividend_value',
56
+ 'informationId': 'information_id',
57
+ 'positionReason': 'position_reason',
58
+ 'firstHoldingDate': 'first_holding_date',
59
+ 'transCurrCd': 'transaction_currency_code',
60
+ 'fxRate': 'exchange_rate',
61
+ }
62
+
63
+
64
+ def get_simulate_portfolio_position_hierarchy(client,
65
+ simulate_portfolio_id,
66
+ date):
67
+ """
68
+ 查询模拟组合持仓平铺
69
+
70
+ Args:
71
+ client: DYPMS客户端实例
72
+ simulate_portfolio_id: 模拟组合代码,必传
73
+ date: 特定日期,必传
74
+ """
75
+ url = f"{client.base_url}/lib/simulate/portfolio/v1/positionHierarchy"
76
+ headers = client.get_headers()
77
+
78
+ data = {
79
+ 'accountCode': simulate_portfolio_id,
80
+ 'date': date
81
+ }
82
+
83
+ try:
84
+ response = requests.post(url, headers=headers, json=data)
85
+ r = get_response_json_with_check(response)
86
+
87
+ rows = []
88
+ for item in r.get('list'):
89
+ row = {}
90
+ for api_field, our_field in field_mapping.items():
91
+ row[our_field] = item.get(api_field, None)
92
+ rows.append(row)
93
+
94
+ df = pd.DataFrame(rows)
95
+ return df
96
+ except Exception as e:
97
+ raise e
@@ -0,0 +1,120 @@
1
+ import requests
2
+ import time
3
+ import pandas as pd
4
+ from .util import get_response_json_with_check2
5
+
6
+
7
+ field_mapping = {
8
+ 'date': 'date',
9
+ 'name': 'style_factor',
10
+ 'value': 'value' # 这里需要根据实际返回的字段名进行调整
11
+ }
12
+
13
+
14
+ def get_style_attr_trend(client, simulate_portfolio_id):
15
+ """
16
+ 获取风格归因趋势
17
+
18
+ Args:
19
+ client: DYPMS客户端实例
20
+ simulate_portfolio_id: 组合代码,必传
21
+ """
22
+ # 1. 调用计算接口
23
+ calc_url = f"{client.base_url}/lib/simulate/portfolio/v1/styleAttrTrend"
24
+ headers = client.get_headers()
25
+ params = {
26
+ 'accountCode': simulate_portfolio_id
27
+ }
28
+
29
+ try:
30
+ # 发送计算请求
31
+ response = requests.get(calc_url, headers=headers, params=params)
32
+ calc_result = get_response_json_with_check2(response)
33
+
34
+ # 获取计算任务ID
35
+ task_id = calc_result.get('id')
36
+ if not task_id:
37
+ raise Exception("计算接口未返回有效的任务ID")
38
+
39
+ # 2. 轮询接口,每隔3秒一次,最多轮询10分钟
40
+ polling_url = f"{client.base_url}/lib/common/v1/polling"
41
+ max_polling_time = 10 * 60 # 10分钟
42
+ polling_interval = 3 # 3秒
43
+ start_time = time.time()
44
+
45
+ while True:
46
+ # 检查是否超时
47
+ elapsed_time = time.time() - start_time
48
+ if elapsed_time > max_polling_time:
49
+ raise Exception(f"轮询超时,超过{max_polling_time}秒")
50
+
51
+ # 发送轮询请求
52
+ polling_params = {'id': task_id}
53
+ polling_response = requests.get(polling_url, headers=headers, params=polling_params)
54
+ polling_result = get_response_json_with_check2(polling_response)
55
+
56
+ # 检查轮询结果
57
+ if polling_result.get('error'):
58
+ raise Exception(f"计算失败: {polling_result.get('errorMsg', '未知错误')}")
59
+
60
+ if polling_result.get('complete'):
61
+ final_result = polling_result.get('finalResult')
62
+ if not final_result:
63
+ raise Exception("计算完成但未返回结果数据")
64
+
65
+ # 3. 解析结果并转换为DataFrame
66
+ # 初始化数据存储结构
67
+ data_by_date_factor = {}
68
+
69
+ # 定义数据类型与字段的映射关系
70
+ data_mappings = [
71
+ ('portfolioReturn', 'accumulated_style_return'),
72
+ ('activeReturn', 'active_accumulated_style_return'),
73
+ ('portfolioWeight', 'style_exposure'), # weight就是暴露
74
+ ('activeWeight', 'active_style_exposure') # weight就是暴露
75
+ ]
76
+
77
+ # 处理所有数据类型
78
+ for data_key, field_name in data_mappings:
79
+ data_list = final_result.get(data_key, [])
80
+ for item in data_list:
81
+ date = item.get('date')
82
+ factor_name = item.get('name')
83
+ factor_type = item.get('factorType')
84
+ value = item.get('value')
85
+
86
+ # 只处理风格因子
87
+ if factor_type != 'style':
88
+ continue
89
+
90
+ # 确保数据结构存在
91
+ key = (date, factor_name)
92
+ if key not in data_by_date_factor:
93
+ data_by_date_factor[key] = {
94
+ 'date': date,
95
+ 'style_factor': factor_name,
96
+ 'style_exposure': 0.0,
97
+ 'active_style_exposure': 0.0,
98
+ 'accumulated_style_return': 0.0,
99
+ 'active_accumulated_style_return': 0.0
100
+ }
101
+
102
+ # 设置对应字段的值
103
+ data_by_date_factor[key][field_name] = value
104
+
105
+ # 转换为数据行列表
106
+ rows = list(data_by_date_factor.values())
107
+
108
+ # 转换为DataFrame
109
+ df = pd.DataFrame(rows)
110
+
111
+ # 按日期降序,因子名称降序排序
112
+ df = df.sort_values(by=['date', 'style_factor'], ascending=[False, False])
113
+
114
+ return df
115
+
116
+ # 等待指定时间后继续轮询
117
+ time.sleep(polling_interval)
118
+
119
+ except Exception as e:
120
+ raise e
DYPMS/api/heartbeat.py ADDED
@@ -0,0 +1,13 @@
1
+ import requests
2
+ from .util import get_response_json_with_check
3
+
4
+
5
+ def heartbeat(client):
6
+
7
+ url = f"{client.base_url}/lib/monitor/v1/heartbeat"
8
+ headers = client.get_headers()
9
+ try:
10
+ response = requests.get(url, headers=headers)
11
+ get_response_json_with_check(response)
12
+ except Exception as e:
13
+ raise e
DYPMS/api/util.py ADDED
@@ -0,0 +1,17 @@
1
+
2
+ def get_response_json_with_check(response):
3
+ if response.status_code != 200:
4
+ response.raise_for_status()
5
+ r = response.json()
6
+ if r.get('code') == -403:
7
+ raise Exception("token认证失败")
8
+ if r.get('code') != 'S00000':
9
+ raise Exception(r.get('message'))
10
+ return r
11
+
12
+
13
+ # 仅校验http状态码,不校验业务状态码(适用于比较老的接口)
14
+ def get_response_json_with_check2(response):
15
+ if response.status_code != 200:
16
+ response.raise_for_status()
17
+ return response.json()
DYPMS/client.py ADDED
@@ -0,0 +1,45 @@
1
+ from .api.heartbeat import heartbeat
2
+ from .api.get_simulate_portfolio_list import get_simulate_portfolio_list
3
+ from .api.get_simulate_portfolio_position import get_simulate_portfolio_position
4
+ from .api.get_simulate_portfolio_position_hierarchy import get_simulate_portfolio_position_hierarchy
5
+ from .api.get_simulate_portfolio_performance_indicators import get_simulate_portfolio_performance_indicators
6
+ from .api.get_simulate_portfolio_net import get_simulate_portfolio_net
7
+ from .api.get_style_attr_trend import get_style_attr_trend
8
+
9
+
10
+ class Client:
11
+
12
+ _instance = None
13
+
14
+ def __init__(self, token='', env='prd'):
15
+ self.token = token
16
+ if env == 'prd':
17
+ self.base_url = "https://gw.datayes.com/aladdin_mof"
18
+ elif env == 'qa':
19
+ self.base_url = "https://gw.datayes-stg.com/mom_aladdin_qa"
20
+ elif env == 'stg':
21
+ self.base_url = "https://gw.datayes-stg.com/mom_aladdin_stg"
22
+ else:
23
+ raise ValueError("error env")
24
+ heartbeat(self)
25
+ Client._instance = self
26
+
27
+ @staticmethod
28
+ def get_instance():
29
+ if Client._instance is None:
30
+ raise RuntimeError("Client未初始化,请先实例化Client")
31
+ return Client._instance
32
+
33
+ def get_headers(self):
34
+ return {
35
+ 'Content-Type': 'application/json',
36
+ 'Authorization': f'Bearer {self.token}'
37
+ }
38
+
39
+
40
+ Client.get_simulate_portfolio_list = get_simulate_portfolio_list
41
+ Client.get_simulate_portfolio_position = get_simulate_portfolio_position
42
+ Client.get_simulate_portfolio_position_hierarchy = get_simulate_portfolio_position_hierarchy
43
+ Client.get_simulate_portfolio_performance_indicators = get_simulate_portfolio_performance_indicators
44
+ Client.get_simulate_portfolio_net = get_simulate_portfolio_net
45
+ Client.get_style_attr_trend = get_style_attr_trend
DYPMS/enums.py ADDED
@@ -0,0 +1,56 @@
1
+ from enum import Enum
2
+
3
+
4
+ class PenetrateType(Enum):
5
+ NO_PENETRATE = "不穿透"
6
+ FOF_QUARTER = "FOF穿透(季报/中报/年报)"
7
+ FOF_SEMI = "FOF穿透(中报/年报)"
8
+ MOM = "MOM穿透"
9
+ ALL = "全部穿透"
10
+
11
+
12
+ class PositionField(Enum):
13
+ CLASS = "资产分类"
14
+ DATE = "日期"
15
+ ASSET_NAME = "资产名称"
16
+ ASSET_CODE = "资产代码"
17
+ SECURITY_TYPE = "证券品种"
18
+ TRADING_MARKET = "交易市场"
19
+ CURRENT_CLEAN_PRICE = "当前净价"
20
+ ACCRUED_INTEREST = "应计利息"
21
+ PRICE_CHANGE = "涨跌"
22
+ POSITION_QUANTITY = "持仓数量"
23
+ POSITION_MARKET_VALUE = "持仓市值"
24
+ POSITION_WEIGHT_NET_ASSETS = "持仓权重(净资产)"
25
+ DAILY_PROFIT_LOSS = "当日盈亏"
26
+ DAILY_PROFIT_LOSS_RATE = "当日盈亏率"
27
+ FLOATING_PROFIT_LOSS = "浮动盈亏"
28
+ FLOATING_PROFIT_LOSS_RATE = "浮动盈亏率"
29
+ CUMULATIVE_PROFIT_LOSS = "累计盈亏"
30
+ CUMULATIVE_PROFIT_LOSS_RATE = "累计盈亏率"
31
+ POSITION_COST = "持仓成本"
32
+ INTEREST_INCOME = "利息收入"
33
+ REALIZED_PROFIT_LOSS = "已实现盈亏"
34
+ MATURITY_DATE = "到期日"
35
+ TRADING_CHANNEL = "交易通道"
36
+ POSITION_DIRECTION = "持仓方向"
37
+ LATEST_PRICE = "最新价"
38
+ POSITION_WEIGHT_TOTAL_ASSETS = "持仓权重(总资产)"
39
+ POSITION_WEIGHT_TOTAL_COST = "持仓权重(总成本)"
40
+ COST_PRICE = "成本价格"
41
+ AMORTIZED_COST = "摊薄成本"
42
+ VALUATION_EXCHANGE_RATE = "估值汇率"
43
+ MARKET_QUOTATION_TIME = "行情时间"
44
+ POSITION_BUILDING_DATE = "建仓日期"
45
+ ISSUING_ENTITY = "发行主体"
46
+ REMAINING_MATURITY = "剩余期限"
47
+ BOND_RATING_AGENCY = "债项评级机构"
48
+ BOND_RATING = "债项评级"
49
+ MARGIN_REQUIREMENT = "占用保证金"
50
+ CITY = "城市"
51
+ PROVINCE = "省份"
52
+ ISSUER_RATING_YY = "主体评级(YY)"
53
+ ISSUER_RATING_DATE = "主体评级日期"
54
+ ISSUER_RATING = "主体评级"
55
+ BOND_RATING_DATE = "债项评级日期"
56
+ ISSUER_RATING_AGENCY = "主体评级机构"
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.4
2
+ Name: DYPMS
3
+ Version: 0.1
4
+ Summary: 通联数据PMS系统数据SDK
5
+ Author-email: songjiangduo <jiangduo.song@datayes.com>
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.6
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Dynamic: license-file
13
+
14
+ 可用于调取DataYes!pro中的模拟组合数据
@@ -0,0 +1,17 @@
1
+ DYPMS/__init__.py,sha256=d122Awe2ObfaEUQfOvLE8oP28F7yxE-qxqh_18Kcyac,885
2
+ DYPMS/client.py,sha256=g7GN0nKMCSgkNeE1QYg4W2deIlaXga2vDKswJ2tsfpo,1834
3
+ DYPMS/enums.py,sha256=PBA4tTVRT0-LSG8T5ySHnyt9ZH9ZyCYM1HL7LIxyAnM,1998
4
+ DYPMS/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ DYPMS/api/get_simulate_portfolio_list.py,sha256=1hsMbmQPg_taoStEV2xffVpzczKKtTNU4fmDlsRTXIM,1490
6
+ DYPMS/api/get_simulate_portfolio_net.py,sha256=BZO8fKDcy6sfKp8_0wW5U6yTVvte3J4eDdWZH-2VTek,1315
7
+ DYPMS/api/get_simulate_portfolio_performance_indicators.py,sha256=-AndaAVlJ6NsWqZh92iw_DOJY0ulyUC4qYG8TMEuKbc,1851
8
+ DYPMS/api/get_simulate_portfolio_position.py,sha256=0Jgr3ZH0kBZ9bc6wfz8A-rbQC8gn4mDQ7T7UmHrcXT4,6163
9
+ DYPMS/api/get_simulate_portfolio_position_hierarchy.py,sha256=lQWJovKS583Hx6AnVNFwzPLHRg-tvcTt07N635pf-R4,3239
10
+ DYPMS/api/get_style_attr_trend.py,sha256=SW5xDQAOR9K7104cufkJ7syhWeDs1QHWy74lc6piHC8,4484
11
+ DYPMS/api/heartbeat.py,sha256=jDjiXRqee4QtGKR7nEoo4VhnlG_wvjT3aMXYizTNt1M,333
12
+ DYPMS/api/util.py,sha256=UUZlDOKwyf-DvlehEqAMCkfOsRRX6_ftyHCHpFo9VJ0,536
13
+ dypms-0.1.dist-info/licenses/LICENSE,sha256=WOCX9n2629PC9kRp-MvyMGR4DrNHG7_Q1Woo6QotwZ4,1130
14
+ dypms-0.1.dist-info/METADATA,sha256=oZFeAboqA1L4MJHdiVIplNYvj7_v7-u6w0ssy4akZdc,422
15
+ dypms-0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ dypms-0.1.dist-info/top_level.txt,sha256=zRRbJZFPWVwbkxb2JKCz_CqUFabxsGg9DBwZxRoi99Y,6
17
+ dypms-0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,20 @@
1
+ 通联数据机密
2
+ --------------------------------------------------------------------
3
+ 通联数据股份公司版权所有 © 2013-$today.year
4
+
5
+ 注意:本文所载所有信息均属于通联数据股份公司资产。本文所包含的知识和技术概念均属于
6
+ 通联数据产权,并可能由中国、美国和其他国家专利或申请中的专利所覆盖,并受商业秘密或
7
+ 版权法保护。
8
+ 除非事先获得通联数据股份公司书面许可,严禁传播文中信息或复制本材料。
9
+
10
+ DataYes CONFIDENTIAL
11
+ --------------------------------------------------------------------
12
+ Copyright © 2013-$today.year DataYes, All Rights Reserved.
13
+
14
+ NOTICE: All information contained herein is the property of DataYes
15
+ Incorporated. The intellectual and technical concepts contained herein are
16
+ proprietary to DataYes Incorporated, and may be covered by China, U.S. and
17
+ Other Countries Patents, patents in process, and are protected by trade
18
+ secret or copyright law.
19
+ Dissemination of this information or reproduction of this material is
20
+ strictly forbidden unless prior written permission is obtained from DataYes.
@@ -0,0 +1 @@
1
+ DYPMS