quantification 0.1.0__py3-none-any.whl → 0.1.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.
Files changed (78) hide show
  1. quantification/__init__.py +3 -2
  2. quantification/api/__init__.py +3 -0
  3. quantification/api/akshare/__init__.py +1 -0
  4. quantification/api/akshare/akshare.py +17 -0
  5. quantification/api/akshare/delegate/__init__.py +6 -0
  6. quantification/api/akshare/delegate/macro_china_fdi.py +46 -0
  7. quantification/api/akshare/delegate/macro_china_lpr.py +43 -0
  8. quantification/api/akshare/delegate/macro_china_qyspjg.py +51 -0
  9. quantification/api/akshare/delegate/macro_china_shrzgm.py +47 -0
  10. quantification/api/akshare/delegate/macro_cnbs.py +47 -0
  11. quantification/api/akshare/delegate/stock_zh_a_hist.py +77 -0
  12. quantification/api/akshare/setting.py +5 -0
  13. quantification/api/api.py +11 -0
  14. quantification/api/api.pyi +21 -0
  15. quantification/api/tushare/__init__.py +1 -0
  16. quantification/api/tushare/delegate/__init__.py +7 -0
  17. quantification/api/tushare/delegate/balancesheet.py +66 -0
  18. quantification/api/tushare/delegate/cashflow.py +29 -0
  19. quantification/api/tushare/delegate/common.py +64 -0
  20. quantification/api/tushare/delegate/daily_basic.py +81 -0
  21. quantification/api/tushare/delegate/fina_indicator.py +20 -0
  22. quantification/api/tushare/delegate/income.py +34 -0
  23. quantification/api/tushare/delegate/index_daily.py +61 -0
  24. quantification/api/tushare/delegate/pro_bar.py +80 -0
  25. quantification/api/tushare/setting.py +5 -0
  26. quantification/api/tushare/tushare.py +17 -0
  27. quantification/core/__init__.py +9 -0
  28. quantification/core/asset/__init__.py +6 -0
  29. quantification/core/asset/base_asset.py +96 -0
  30. quantification/core/asset/base_broker.py +42 -0
  31. quantification/core/asset/broker.py +108 -0
  32. quantification/core/asset/cash.py +75 -0
  33. quantification/core/asset/stock.py +268 -0
  34. quantification/core/cache.py +93 -0
  35. quantification/core/configure.py +15 -0
  36. quantification/core/data/__init__.py +5 -0
  37. quantification/core/data/base_api.py +109 -0
  38. quantification/core/data/base_delegate.py +73 -0
  39. quantification/core/data/field.py +213 -0
  40. quantification/core/data/panel.py +42 -0
  41. quantification/core/env.py +25 -0
  42. quantification/core/logger.py +94 -0
  43. quantification/core/strategy/__init__.py +3 -0
  44. quantification/core/strategy/base_strategy.py +66 -0
  45. quantification/core/strategy/base_trigger.py +69 -0
  46. quantification/core/strategy/base_use.py +69 -0
  47. quantification/core/trader/__init__.py +7 -0
  48. quantification/core/trader/base_order.py +45 -0
  49. quantification/core/trader/base_stage.py +16 -0
  50. quantification/core/trader/base_trader.py +173 -0
  51. quantification/core/trader/collector.py +47 -0
  52. quantification/core/trader/order.py +23 -0
  53. quantification/core/trader/portfolio.py +72 -0
  54. quantification/core/trader/query.py +29 -0
  55. quantification/core/trader/report.py +76 -0
  56. quantification/core/util.py +181 -0
  57. quantification/default/__init__.py +5 -0
  58. quantification/default/stage/__init__.py +1 -0
  59. quantification/default/stage/cn_stock.py +23 -0
  60. quantification/default/strategy/__init__.py +1 -0
  61. quantification/default/strategy/simple/__init__.py +1 -0
  62. quantification/default/strategy/simple/strategy.py +8 -0
  63. quantification/default/trader/__init__.py +2 -0
  64. quantification/default/trader/a_factor/__init__.py +1 -0
  65. quantification/default/trader/a_factor/trader.py +27 -0
  66. quantification/default/trader/simple/__init__.py +1 -0
  67. quantification/default/trader/simple/trader.py +8 -0
  68. quantification/default/trigger/__init__.py +1 -0
  69. quantification/default/trigger/trigger.py +63 -0
  70. quantification/default/use/__init__.py +1 -0
  71. quantification/default/use/factors/__init__.py +2 -0
  72. quantification/default/use/factors/factor.py +205 -0
  73. quantification/default/use/factors/use.py +38 -0
  74. quantification-0.1.1.dist-info/METADATA +19 -0
  75. quantification-0.1.1.dist-info/RECORD +76 -0
  76. {quantification-0.1.0.dist-info → quantification-0.1.1.dist-info}/WHEEL +1 -1
  77. quantification-0.1.0.dist-info/METADATA +0 -13
  78. quantification-0.1.0.dist-info/RECORD +0 -4
@@ -0,0 +1,34 @@
1
+ import tushare as ts
2
+
3
+ from quantification.core import (
4
+ Field,
5
+ Config,
6
+ cache_query
7
+ )
8
+
9
+ from .common import TushareSheetDelegate
10
+ from ..setting import TuShareSetting
11
+
12
+
13
+ class IncomeDelegate(TushareSheetDelegate):
14
+ pair = [
15
+ (Field.IS_营业总收入, "total_revenue"),
16
+ (Field.IS_营业总成本, "total_cogs"),
17
+ (Field.IS_营业利润, "operate_profit"),
18
+ (Field.IS_利润总额, "total_profit"),
19
+ (Field.IS_息税前利润, "ebit"),
20
+ (Field.IS_息税折旧摊销前利润, "ebitda"),
21
+ (Field.IS_所得税费用, "income_tax"),
22
+ (Field.IS_净利润, "n_income"),
23
+ (Field.IS_归母净利润, "n_income_attr_p"),
24
+ (Field.IS_综合收益, "t_compr_income"),
25
+ (Field.IS_归母综合收益, "compr_inc_attr_p"),
26
+ (Field.IS_销售费用, "sell_exp"),
27
+ (Field.IS_管理费用, "admin_exp"),
28
+ (Field.IS_财务费用, "fin_exp"),
29
+ (Field.IS_研发费用, "rd_exp"),
30
+ ]
31
+
32
+ def __init__(self, config: Config, setting: TuShareSetting):
33
+ super().__init__(config, setting)
34
+ self.api = cache_query()(ts.pro_api(setting.tushare_token).income)
@@ -0,0 +1,61 @@
1
+ from datetime import date, datetime, time
2
+
3
+ import pandas as pd
4
+ import tushare as ts
5
+
6
+ from quantification.core import (
7
+ Field,
8
+ Config,
9
+ cache_query,
10
+ BaseDelegate,
11
+ )
12
+
13
+ from ..setting import TuShareSetting
14
+
15
+
16
+ class IndexDailyDelegate(BaseDelegate[TuShareSetting]):
17
+ pair = [
18
+ (Field.IN_开盘点位, "open"),
19
+ (Field.IN_收盘点位, "close"),
20
+ (Field.IN_最高点位, "high"),
21
+ (Field.IN_最低点位, "low")
22
+ ]
23
+
24
+ def has_field(self, field: Field, **kwargs):
25
+ if self.field2str.get(field) is None:
26
+ return False
27
+
28
+ index = kwargs.get("index")
29
+ assert index is not None, "请传入index='xxx'"
30
+ assert type(index) == str, f"index必须为字符串, 实际为{type(index)}"
31
+
32
+ return True
33
+
34
+ def query(self, start_date: date, end_date: date, fields: list[Field], **kwargs) -> pd.DataFrame:
35
+ data = self.api(
36
+ ts_code=kwargs.get("index"),
37
+ start_date=start_date.strftime("%Y%m%d"),
38
+ end_date=end_date.strftime("%Y%m%d"),
39
+ )
40
+
41
+ data = self.rename_columns(data, "trade_date")
42
+ data = self.use_date_index(data)
43
+
44
+ return data
45
+
46
+ def mask(self, data: pd.DataFrame, start_date: date, end_date: date, fields: list[Field], **kwargs) -> pd.DataFrame:
47
+ mask = pd.DataFrame(index=data.index, columns=data.columns)
48
+ index = pd.Series(mask.index)
49
+
50
+ for field in fields:
51
+ match field:
52
+ case Field.IN_开盘点位:
53
+ mask[field] = list(map(lambda x: datetime.combine(x, time(9, 30, 0)), index))
54
+ case Field.IN_收盘点位 | Field.IN_最高点位 | Field.IN_最低点位:
55
+ mask[field] = list(map(lambda x: datetime.combine(x, time(17, 0, 0)), index))
56
+
57
+ return mask
58
+
59
+ def __init__(self, config: Config, setting: TuShareSetting):
60
+ super().__init__(config, setting)
61
+ self.api = cache_query()(ts.pro_api(setting.tushare_token).index_daily)
@@ -0,0 +1,80 @@
1
+ from datetime import date, datetime, time
2
+
3
+ import pandas as pd
4
+ import tushare as ts
5
+
6
+ from quantification.core import (
7
+ Field,
8
+ Stock,
9
+ cache_query,
10
+ BaseDelegate,
11
+ StockExchange as E
12
+ )
13
+
14
+ from ..setting import TuShareSetting
15
+
16
+ api = cache_query()(ts.pro_bar)
17
+
18
+
19
+ class ProBarDelegate(BaseDelegate[TuShareSetting]):
20
+ pair = [
21
+ (Field.ST_昨收价, "pre_close"),
22
+ (Field.ST_开盘价, "open"),
23
+ (Field.ST_最高价, "high"),
24
+ (Field.ST_最低价, "low"),
25
+ (Field.ST_收盘价, "close"),
26
+ (Field.ST_涨跌额, "change"),
27
+ (Field.ST_涨跌幅, "pct_chg"),
28
+ (Field.ST_成交量, "vol"),
29
+ (Field.ST_成交额, "amount")
30
+ ]
31
+
32
+ def has_field(self, field: Field, **kwargs):
33
+ if self.field2str.get(field) is None:
34
+ return False
35
+
36
+ stock = kwargs.get("stock")
37
+ assert stock is not None, "请传入stock参数, 如stock=Stock['000001']"
38
+ assert issubclass(stock, Stock), f"stock参数必须为Stock子类, 实际为{type(stock)}"
39
+
40
+ if stock.exchange not in [E.SZSE, E.BSE, E.SSE]:
41
+ return False
42
+
43
+ return True
44
+
45
+ def query(self, start_date: date, end_date: date, fields: list[Field], **kwargs) -> pd.DataFrame:
46
+ stock: Stock = kwargs.get("stock")
47
+ exchange = {
48
+ E.SSE: "SH",
49
+ E.SZSE: "SZ",
50
+ E.BSE: "BJ"
51
+ }[stock.exchange]
52
+
53
+ data = api(
54
+ ts_code=f"{stock.symbol}.{exchange}",
55
+ start_date=start_date.strftime("%Y%m%d"),
56
+ end_date=end_date.strftime("%Y%m%d"),
57
+ adj=self.config.adjust
58
+ )
59
+
60
+ data = self.rename_columns(data, "trade_date")
61
+ data = self.use_date_index(data)
62
+
63
+ data[Field.ST_成交额] = data[Field.ST_成交额].apply(lambda x: x / 10)
64
+
65
+ return data
66
+
67
+ def mask(self, data: pd.DataFrame, start_date: date, end_date: date, fields: list[Field], **kwargs) -> pd.DataFrame:
68
+ mask = pd.DataFrame(index=data.index, columns=data.columns)
69
+ index = pd.Series(mask.index)
70
+
71
+ for field in fields:
72
+ match field:
73
+ case Field.ST_昨收价:
74
+ mask[field] = list(map(lambda x: datetime.combine(x, time(0, 0, 0)), index))
75
+ case Field.ST_开盘价:
76
+ mask[field] = list(map(lambda x: datetime.combine(x, time(9, 30, 0)), index))
77
+ case Field.ST_最高价 | Field.ST_最低价 | Field.ST_收盘价 | Field.ST_涨跌额 | Field.ST_涨跌幅 | Field.ST_成交量 | Field.ST_成交额:
78
+ mask[field] = list(map(lambda x: datetime.combine(x, time(17, 0, 0)), index))
79
+
80
+ return mask
@@ -0,0 +1,5 @@
1
+ from pydantic import Field, BaseModel
2
+
3
+
4
+ class TuShareSetting(BaseModel):
5
+ tushare_token: str = Field(description='TuShare接口Token')
@@ -0,0 +1,17 @@
1
+ from quantification.core.data import BaseAPI
2
+
3
+ from .setting import TuShareSetting
4
+ from .delegate import *
5
+
6
+
7
+ class TuShareAPI(BaseAPI[TuShareSetting]):
8
+ setting_class = TuShareSetting
9
+ delegate_classes = [
10
+ ProBarDelegate,
11
+ IncomeDelegate,
12
+ CashflowDelegate,
13
+ IndexDailyDelegate,
14
+ DailyBasicDelegate,
15
+ BalanceSheetDelegate,
16
+ FinanceIndicatorDelegate,
17
+ ]
@@ -0,0 +1,9 @@
1
+ from .data import *
2
+ from .asset import *
3
+ from .trader import *
4
+ from .strategy import *
5
+
6
+ from .util import inject
7
+ from .cache import cache_query
8
+ from .logger import logger
9
+ from .configure import Config, config
@@ -0,0 +1,6 @@
1
+ from .base_asset import BaseAsset
2
+ from .base_broker import BaseBroker
3
+
4
+ from .cash import Cash, RMB, HKD, USD
5
+ from .stock import Stock, StockExchange
6
+ from .broker import StockBrokerCN
@@ -0,0 +1,96 @@
1
+ from abc import ABCMeta, abstractmethod
2
+
3
+ from ..env import EnvGetter
4
+
5
+
6
+ class BaseAssetMeta(ABCMeta):
7
+ def __repr__(self: "BaseAsset"):
8
+ return self.name()
9
+
10
+ __str__ = __repr__
11
+
12
+
13
+ class BaseAsset(EnvGetter, metaclass=BaseAssetMeta):
14
+ is_closeable = True # 若为True, 当empty时将从Portfolio中移除该资产
15
+
16
+ @classmethod
17
+ @abstractmethod
18
+ def type(cls):
19
+ raise NotImplementedError
20
+
21
+ @classmethod
22
+ @abstractmethod
23
+ def name(cls) -> str:
24
+ raise NotImplementedError
25
+
26
+ @property
27
+ @abstractmethod
28
+ def amount(self, *args, **kwargs) -> int:
29
+ """
30
+ 资产数额
31
+ """
32
+ raise NotImplementedError
33
+
34
+ @property
35
+ @abstractmethod
36
+ def extra(self, *args, **kwargs) -> dict:
37
+ """
38
+ 资产额外信息
39
+ """
40
+ raise NotImplementedError
41
+
42
+ @property
43
+ @abstractmethod
44
+ def is_empty(self) -> bool:
45
+ """
46
+ 若为True, 则会在Portfolio中移除该资产
47
+ """
48
+ raise NotImplementedError
49
+
50
+ @abstractmethod
51
+ def available(self, *args, **kwargs):
52
+ """
53
+ 获取该资产可用于出售的部分
54
+ """
55
+ raise NotImplementedError
56
+
57
+ @property
58
+ @abstractmethod
59
+ def copy(self, *args, **kwargs):
60
+ """
61
+ 复制资产对象
62
+ """
63
+ raise NotImplementedError
64
+
65
+ @abstractmethod
66
+ def __add__(self, other: "BaseAsset"):
67
+ """
68
+ 购买同一种资产
69
+ :param other: 同一种资产
70
+ """
71
+ raise NotImplementedError
72
+
73
+ @abstractmethod
74
+ def __sub__(self, other: "BaseAsset"):
75
+ """
76
+ 出售该资产的一部分
77
+ :param other: 同一种资产
78
+ """
79
+ raise NotImplementedError
80
+
81
+ @abstractmethod
82
+ def __eq__(self, other: "BaseAsset"):
83
+ """
84
+ 判断是否为同一种资产
85
+ :param other: 任意资产
86
+ """
87
+ raise NotImplementedError
88
+
89
+ @abstractmethod
90
+ def __repr__(self):
91
+ raise NotImplementedError
92
+
93
+ __str__ = __repr__
94
+
95
+
96
+ __all__ = ["BaseAsset"]
@@ -0,0 +1,42 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import TypeVar, Generic, TYPE_CHECKING
3
+ from datetime import date
4
+
5
+ from ..env import EnvGetter
6
+
7
+ if TYPE_CHECKING:
8
+ from .base_asset import BaseAsset
9
+ from ..data import BaseAPI
10
+ from ..trader import BaseOrder, BaseStage, Result
11
+
12
+ AssetType = TypeVar('AssetType', bound="BaseAsset")
13
+
14
+
15
+ class BaseBroker(Generic[AssetType], ABC, EnvGetter):
16
+ def __init__(self, api: "BaseAPI", start_date: date, end_date: date, stage: type["BaseStage"]):
17
+ super().__init__()
18
+
19
+ self.api = api
20
+ self.start_date = start_date
21
+ self.end_date = end_date
22
+ self.stage = stage
23
+
24
+ @abstractmethod
25
+ def matchable(self, asset: "BaseAsset") -> bool:
26
+ raise NotImplementedError
27
+
28
+ @abstractmethod
29
+ def execute_order(self, order: "BaseOrder[AssetType]") -> "Result":
30
+ raise NotImplementedError
31
+
32
+ @abstractmethod
33
+ def liquidate_asset(self, asset: "BaseAsset", day: date, stage: "BaseStage") -> int:
34
+ raise NotImplementedError
35
+
36
+ def __repr__(self):
37
+ return f"<{self.__class__.__name__}>"
38
+
39
+ __str__ = __repr__
40
+
41
+
42
+ __all__ = ['BaseBroker']
@@ -0,0 +1,108 @@
1
+ from typing import TYPE_CHECKING
2
+ from datetime import timedelta, date, time
3
+
4
+ from pandas import to_datetime
5
+
6
+ from .cash import RMB
7
+ from .stock import Stock
8
+ from .stock import StockExchange as E
9
+ from .base_broker import BaseBroker
10
+
11
+ from ..logger import logger
12
+ from ..data.field import Field
13
+ from ..data.base_api import BaseAPI
14
+ from ..trader.order import StockOrder
15
+ from ..trader.base_order import Result
16
+ from ..trader.base_stage import BaseStage
17
+
18
+ if TYPE_CHECKING:
19
+ from .base_asset import BaseAsset
20
+
21
+
22
+ class StockBrokerCN(BaseBroker[Stock]):
23
+ def matchable(self, asset: "BaseAsset") -> bool:
24
+ if not isinstance(asset, Stock):
25
+ logger.trace(f"{asset}不是股票, {self}无法处理, 交给下一个Broker")
26
+ return False
27
+
28
+ if not asset.exchange in [E.SSE, E.SZSE, E.BSE]:
29
+ logger.trace(f"{asset}不属于上交所|深交所|北交所, {self}无法处理, 交给下一个Broker")
30
+ return False
31
+
32
+ return True
33
+
34
+ def execute_order(self, order: StockOrder) -> Result:
35
+ assert self.env is not None, "无法获取env"
36
+
37
+ match self.env.time:
38
+ case time(hour=9, minute=30, second=0):
39
+ field = Field.ST_开盘价
40
+ case time(hour=15, minute=0, second=0):
41
+ field = Field.ST_收盘价
42
+ case _:
43
+ raise ValueError("StockBrokerCN只支持在9:30和15:00撮合交易")
44
+
45
+ df = self.api.query(
46
+ self.start_date,
47
+ self.end_date,
48
+ [Field.ST_开盘价, Field.ST_收盘价],
49
+ stock=Stock[order.asset.symbol]
50
+ )
51
+
52
+ price = df.at[to_datetime(self.env.date), field]
53
+
54
+ logger.trace(f"{self}撮合交易{order}: 日期{self.env.date} 时间{self.env.time} 价格{price}")
55
+
56
+ match order.category:
57
+ case "buy":
58
+ return Result(
59
+ order=order,
60
+ sold=[RMB(price * order.asset.amount)],
61
+ brought=[order.asset],
62
+ )
63
+ case "sell":
64
+ return Result(
65
+ order=order,
66
+ sold=[order.asset],
67
+ brought=[RMB(price * order.asset.amount)],
68
+ )
69
+ case _:
70
+ raise ValueError(f"invalid order category: {order.category}")
71
+
72
+ def liquidate_asset(self, asset: Stock, day: date, stage: BaseStage) -> RMB:
73
+ df = self.api.query(
74
+ self.start_date,
75
+ self.end_date,
76
+ [Field.ST_开盘价, Field.ST_收盘价],
77
+ stock=Stock[asset.symbol]
78
+ )
79
+
80
+ liquidating_value = 0
81
+
82
+ if not to_datetime(day) in df.index:
83
+ for brought_day, brought_share in asset.share_position.items():
84
+ nearest_day = df.index[df.index.searchsorted(to_datetime(day), side='left')]
85
+ liquidating_value += df.at[nearest_day, Field.ST_开盘价] * brought_share
86
+ else:
87
+ for brought_day, brought_share in asset.share_position.items():
88
+ if brought_day < day and stage.time <= time(9, 30):
89
+ liquidating_value += df.at[to_datetime(day), Field.ST_开盘价] * brought_share
90
+
91
+ elif brought_day < day and stage.time <= time(15, 0):
92
+ liquidating_value += df.at[to_datetime(day), Field.ST_收盘价] * brought_share
93
+
94
+ elif (brought_day < day and stage.time >= time(15, 0)) or brought_day == day:
95
+ pos = df.index.get_loc(to_datetime(day)) # 获取位置
96
+ next_day = df.index[pos + 1] # 下一个位置的日期
97
+ liquidating_value += df.at[next_day, Field.ST_开盘价] * brought_share
98
+
99
+ else:
100
+ raise ValueError(f"invalid brought day: {brought_day}")
101
+
102
+ return liquidating_value
103
+
104
+ def __init__(self, api: "BaseAPI", start_date: date, end_date: date, stage: type[BaseStage]):
105
+ super().__init__(api, start_date - timedelta(days=10), end_date + timedelta(days=10), stage)
106
+
107
+
108
+ __all__ = ["StockBrokerCN"]
@@ -0,0 +1,75 @@
1
+ from .base_asset import BaseAsset
2
+
3
+ cash_family: dict[str:type["Cash"]] = {}
4
+
5
+
6
+ class Cash(BaseAsset):
7
+ symbol: str = None
8
+ is_closeable = False
9
+
10
+ @classmethod
11
+ def type(cls, *args, **kwargs):
12
+ return "Cash"
13
+
14
+ @classmethod
15
+ def name(cls, *args, **kwargs):
16
+ return f"现金{cls.symbol}" if cls.symbol else "全部现金"
17
+
18
+ @property
19
+ def amount(self, *args, **kwargs):
20
+ return self.value
21
+
22
+ @property
23
+ def extra(self, *args, **kwargs):
24
+ return {}
25
+
26
+ @property
27
+ def is_empty(self):
28
+ return self.value == 0
29
+
30
+ @property
31
+ def copy(self):
32
+ return Cash[self.symbol](self.value)
33
+
34
+ def available(self, *args, **kwargs):
35
+ return Cash[self.symbol](self.value)
36
+
37
+ def __add__(self, other: "Cash"):
38
+ assert self == other, f"只能和Cash相加, 实际类型{type(other)}"
39
+
40
+ return Cash[self.symbol](self.value + other.value)
41
+
42
+ def __sub__(self, other: "Cash"):
43
+ assert self == other, f"只能和Cash相减, 实际类型{type(other)}"
44
+
45
+ return Cash[self.symbol](self.value - other.value)
46
+
47
+ def __eq__(self, other: "Cash"):
48
+ return isinstance(other, Cash) and self.symbol == other.symbol
49
+
50
+ def __repr__(self):
51
+ return f"{self.name()}({self.value}元)"
52
+
53
+ __str__ = __repr__
54
+
55
+ def __init__(self, value: float = 0):
56
+ assert self.symbol is not None, "未指定现金类型, 无法实例化"
57
+ assert value >= 0, f"现金金额不能为负, 实际为{value}"
58
+ self.value = value
59
+
60
+ def __class_getitem__(cls, symbol: str):
61
+ if not cash_family.get(symbol):
62
+ cash_family[symbol] = type(
63
+ f"Cash{symbol}",
64
+ (Cash,),
65
+ {"symbol": symbol},
66
+ )
67
+
68
+ return cash_family[symbol]
69
+
70
+
71
+ RMB = Cash["RMB"]
72
+ HKD = Cash["HKD"]
73
+ USD = Cash["USD"]
74
+
75
+ __all__ = ["Cash", "RMB", "HKD", "USD"]