Skip to content

Commit

Permalink
1) move portfolio to contract schema
Browse files Browse the repository at this point in the history
2) add fund entity
  • Loading branch information
foolcage committed Jan 4, 2021
1 parent 6a08211 commit 8210e5e
Show file tree
Hide file tree
Showing 25 changed files with 225 additions and 94 deletions.
5 changes: 3 additions & 2 deletions zvt/contract/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class AdjustType(enum.Enum):


from . import zvt_context
from .schema import Mixin, NormalMixin, EntityMixin, NormalEntityMixin
from .schema import Mixin, NormalMixin, EntityMixin, NormalEntityMixin, PortfolioStock, Portfolio, PortfolioStockHistory

__all__ = ['IntervalLevel', 'Mixin', 'NormalMixin', 'EntityMixin', 'NormalEntityMixin', 'zvt_context', 'AdjustType']
__all__ = ['IntervalLevel', 'Mixin', 'NormalMixin', 'EntityMixin', 'NormalEntityMixin', 'zvt_context', 'AdjustType',
'Portfolio', 'PortfolioStock', 'PortfolioStockHistory']
69 changes: 67 additions & 2 deletions zvt/contract/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
from typing import List, Union

import pandas as pd
from sqlalchemy import Column, String, DateTime
from sqlalchemy import Column, String, DateTime, Float
from sqlalchemy.orm import Session

from zvt.contract import IntervalLevel
from zvt.utils.time_utils import date_and_time, is_same_time
from zvt.utils.time_utils import date_and_time, is_same_time, now_pd_timestamp


class Mixin(object):
Expand Down Expand Up @@ -178,11 +178,30 @@ class NormalMixin(Mixin):
updated_timestamp = Column(DateTime)


class Player(Mixin):
# 参与者类型
player_type = Column(String(length=64))
# 所属国家
country = Column(String(length=32))
# 编码
code = Column(String(length=64))
# 名字
name = Column(String(length=128))


class EntityMixin(Mixin):
# 标的类型
entity_type = Column(String(length=64))
# 所属交易所
exchange = Column(String(length=32))
# 编码
code = Column(String(length=64))
# 名字
name = Column(String(length=128))
# 上市日
list_date = Column(DateTime)
# 退市日
end_date = Column(DateTime)

@classmethod
def get_trading_dates(cls, start_date=None, end_date=None):
Expand Down Expand Up @@ -286,3 +305,49 @@ class NormalEntityMixin(EntityMixin):
created_timestamp = Column(DateTime, default=pd.Timestamp.now())
# the record updated time in db, some recorder would check it for whether need to refresh
updated_timestamp = Column(DateTime)


class Portfolio(EntityMixin):
@classmethod
def get_stocks(cls,
code=None, codes=None, ids=None, timestamp=now_pd_timestamp(), provider=None):
"""
:param code: portfolio(etf/block/index...) code
:param codes: portfolio(etf/block/index...) codes
:param timestamp:
:param provider:
:return:
"""
from zvt.contract.api import get_schema_by_name
schema_str = f'{cls.__name__}Stock'
portfolio_stock = get_schema_by_name(schema_str)
return portfolio_stock.query_data(provider=provider, code=code, codes=codes, timestamp=timestamp, ids=ids)


# 组合(Etf,Index,Block)和个股(Stock)的关系 应该继承自该类
# 该基础类可以这样理解:
# entity为组合本身,其包含了stock这种entity,timestamp为持仓日期,从py的"你知道你在干啥"的哲学出发,不加任何约束
class PortfolioStock(EntityMixin):
stock_id = Column(String)
stock_code = Column(String(length=64))
stock_name = Column(String(length=128))


# 支持时间变化,报告期标的调整
class PortfolioStockHistory(PortfolioStock):
# 报告期,season1,half_year,season3,year
report_period = Column(String(length=32))
# 3-31,6-30,9-30,12-31
report_date = Column(DateTime)

# 占净值比例
proportion = Column(Float)
# 持有股票的数量
shares = Column(Float)
# 持有股票的市值
market_cap = Column(Float)


__all__ = ['EntityMixin', 'Mixin', 'NormalMixin', 'NormalEntityMixin', 'Portfolio', 'PortfolioStock',
'PortfolioStockHistory']
50 changes: 50 additions & 0 deletions zvt/domain/meta/fund.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base

from zvt.contract import EntityMixin, PortfolioStockHistory
from zvt.contract.register import register_entity, register_schema

FundMetaBase = declarative_base()


# 个股
@register_entity(entity_type='fund')
class Fund(FundMetaBase, EntityMixin):
__tablename__ = 'fund'
# 基金管理人
advisor = Column(String(length=100))
# 基金托管人
trustee = Column(String(length=100))

# 编码 基金运作方式
# 401001 开放式基金
# 401002 封闭式基金
# 401003 QDII
# 401004 FOF
# 401005 ETF
# 401006 LOF
# 基金运作方式编码
operate_mode_id = Column(Integer)
# 基金运作方式
operate_mode = Column(String(length=32))

# 编码 基金类别
# 402001 股票型
# 402002 货币型
# 402003 债券型
# 402004 混合型
# 402005 基金型
# 402006 贵金属
# 402007 封闭式
# 投资标的类型编码
underlying_asset_type_id = Column(Integer)
# 投资标的类型
underlying_asset_type = Column(String(length=32))


class FundStock(FundMetaBase, PortfolioStockHistory):
__tablename__ = 'fund_stock'


register_schema(providers=['joinquant'], db_name='fund_meta', schema_base=FundMetaBase)
66 changes: 10 additions & 56 deletions zvt/domain/meta/stock_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,21 @@

from zvt.contract import EntityMixin
from zvt.contract.register import register_schema, register_entity
from zvt.contract.schema import Portfolio, PortfolioStock, PortfolioStockHistory
from zvt.utils.time_utils import now_pd_timestamp

StockMetaBase = declarative_base()


class BaseSecurity(EntityMixin):
# 上市日
list_date = Column(DateTime)
# 退市日
end_date = Column(DateTime)


class BasePortfolio(BaseSecurity):
@classmethod
def get_stocks(cls,
code=None, codes=None, ids=None, timestamp=now_pd_timestamp(), provider=None):
"""
:param code: portfolio(etf/block/index...) code
:param codes: portfolio(etf/block/index...) codes
:param timestamp:
:param provider:
:return:
"""
portfolio_stock: BasePortfolioStock = eval(f'{cls.__name__}Stock')
return portfolio_stock.query_data(provider=provider, code=code, codes=codes, ids=ids)


# 个股
@register_entity(entity_type='stock')
class Stock(StockMetaBase, BaseSecurity):
class Stock(StockMetaBase, EntityMixin):
__tablename__ = 'stock'


# 板块
@register_entity(entity_type='block')
class Block(StockMetaBase, BasePortfolio):
class Block(StockMetaBase, Portfolio):
__tablename__ = 'block'

# 板块类型,行业(industry),概念(concept)
Expand All @@ -50,7 +28,7 @@ class Block(StockMetaBase, BasePortfolio):

# 指数
@register_entity(entity_type='index')
class Index(StockMetaBase, BasePortfolio):
class Index(StockMetaBase, Portfolio):
__tablename__ = 'index'

# 发布商
Expand All @@ -63,7 +41,7 @@ class Index(StockMetaBase, BasePortfolio):

# etf
@register_entity(entity_type='etf')
class Etf(StockMetaBase, BasePortfolio):
class Etf(StockMetaBase, Portfolio):
__tablename__ = 'etf'
category = Column(String(length=64))

Expand All @@ -73,45 +51,21 @@ def get_stocks(cls, code=None, codes=None, ids=None, timestamp=now_pd_timestamp(
return get_etf_stocks(code=code, codes=codes, ids=ids, timestamp=timestamp, provider=provider)


# 组合(Etf,Index,Block)和个股(Stock)的关系 应该继承自该类
# 该基础类可以这样理解:
# entity为组合本身,其包含了stock这种entity,timestamp为持仓日期,从py的"你知道你在干啥"的哲学出发,不加任何约束
class BasePortfolioStock(EntityMixin):
stock_id = Column(String)
stock_code = Column(String(length=64))
stock_name = Column(String(length=128))


# 支持时间变化,报告期标的调整
class BasePortfolioStockHistory(BasePortfolioStock):
# 报告期,season1,half_year,season3,year
report_period = Column(String(length=32))
# 3-31,6-30,9-30,12-31
report_date = Column(DateTime)

# 占净值比例
proportion = Column(Float)
# 持有股票的数量
shares = Column(Float)
# 持有股票的市值
market_cap = Column(Float)


class BlockStock(StockMetaBase, BasePortfolioStock):
class BlockStock(StockMetaBase, PortfolioStock):
__tablename__ = 'block_stock'


class IndexStock(StockMetaBase, BasePortfolioStockHistory):
class IndexStock(StockMetaBase, PortfolioStockHistory):
__tablename__ = 'index_stock'


class EtfStock(StockMetaBase, BasePortfolioStockHistory):
class EtfStock(StockMetaBase, PortfolioStockHistory):
__tablename__ = 'etf_stock'


# 个股详情
@register_entity(entity_type='stock_detail')
class StockDetail(StockMetaBase, BaseSecurity):
class StockDetail(StockMetaBase, EntityMixin):
__tablename__ = 'stock_detail'

industries = Column(String)
Expand Down Expand Up @@ -141,4 +95,4 @@ class StockDetail(StockMetaBase, BaseSecurity):
schema_base=StockMetaBase)

# the __all__ is generated
__all__ = ['BaseSecurity', 'BasePortfolio', 'Stock', 'Block', 'Index', 'Etf', 'BasePortfolioStock', 'BasePortfolioStockHistory', 'BlockStock', 'IndexStock', 'EtfStock', 'StockDetail']
__all__ = ['Stock', 'Block', 'Index', 'Etf', 'BlockStock', 'IndexStock', 'EtfStock', 'StockDetail']
5 changes: 0 additions & 5 deletions zvt/recorders/joinquant/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
# -*- coding: utf-8 -*-
from zvt.recorders.joinquant.fundamental import *
from zvt.recorders.joinquant.meta import *
from zvt.recorders.joinquant.misc import *
from zvt.recorders.joinquant.overall import *
from zvt.recorders.joinquant.quotes import *
# the __all__ is generated
__all__ = []

Expand Down
14 changes: 10 additions & 4 deletions zvt/recorders/joinquant/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ def to_jq_entity_id(security_item):


def to_entity_id(jq_code: str, entity_type):
code, exchange = jq_code.split('.')
if exchange == 'XSHG':
exchange = 'sh'
elif exchange == 'XSHE':
try:
code, exchange = jq_code.split('.')
if exchange == 'XSHG':
exchange = 'sh'
elif exchange == 'XSHE':
exchange = 'sz'
except:
code = jq_code
exchange = 'sz'

return f'{entity_type}_{exchange}_{code}'
Expand All @@ -51,5 +55,7 @@ def jq_to_report_period(jq_report_type):
if jq_report_type == '年度':
return ReportPeriod.year.value
assert False


# the __all__ is generated
__all__ = ['to_jq_trading_level', 'to_jq_entity_id', 'to_entity_id', 'jq_to_report_period']
5 changes: 1 addition & 4 deletions zvt/recorders/joinquant/fundamental/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# -*- coding: utf-8 -*-

from zvt.recorders.joinquant.fundamental.etf_valuation_recorder import *
from zvt.recorders.joinquant.fundamental.stock_valuation_recorder import *
from zvt.recorders.joinquant.fundamental.joinquant_margin_trading_recorder import *# the __all__ is generated
# the __all__ is generated
__all__ = []

# __init__.py structure:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,4 @@ def record(self, entity, start, end, size, timestamps):
# 上证50
JqChinaEtfValuationRecorder(codes=['512290']).run()
# the __all__ is generated
__all__ = ['JqChinaEtfValuationRecorder']
__all__ = ['JqChinaEtfValuationRecorder']
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ def record(self, entity, start, end, size, timestamps):
if __name__ == '__main__':
MarginTradingRecorder(codes=['000004']).run()
# the __all__ is generated
__all__ = ['MarginTradingRecorder']
__all__ = ['MarginTradingRecorder']
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ def record(self, entity, start, end, size, timestamps):

JqChinaStockValuationRecorder(entity_ids=['stock_sh_600000'], force_update=True).run()
# the __all__ is generated
__all__ = ['JqChinaStockValuationRecorder']
__all__ = ['JqChinaStockValuationRecorder']
7 changes: 5 additions & 2 deletions zvt/recorders/joinquant/meta/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# -*- coding: utf-8 -*-
from zvt.recorders.joinquant.meta.china_stock_meta_recorder import *
from zvt.recorders.joinquant.meta.stock_trade_day_recorder import *
# the __all__ is generated
__all__ = []

# __init__.py structure:
# common code of the package
# export interface in __all__ which contains __all__ of its sub modules

# import all from submodule china_fund_meta_recorder
from .china_fund_meta_recorder import *
from .china_fund_meta_recorder import __all__ as _china_fund_meta_recorder_all
__all__ += _china_fund_meta_recorder_all

# import all from submodule china_stock_meta_recorder
from .china_stock_meta_recorder import *
from .china_stock_meta_recorder import __all__ as _china_stock_meta_recorder_all
Expand Down
Loading

0 comments on commit 8210e5e

Please sign in to comment.