oxtapus 0.4.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.
oxtapus/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ from oxtapus.fipiran import Fipiran
2
+ from oxtapus.rahavard import Rahavard
3
+ from oxtapus.tgju import TGJU
4
+ from oxtapus.tsetmc import TSETMC
5
+
6
+ __all__ = ["TSETMC", "Rahavard", "TGJU", "Fipiran"]
oxtapus/fipiran.py ADDED
@@ -0,0 +1,36 @@
1
+ import polars as pl
2
+
3
+ from oxtapus.models.fipiran import DependencyGraph
4
+ from oxtapus.utils.http import get
5
+ from oxtapus.utils.normalize import normalize_nested_dict
6
+
7
+
8
+ class Fipiran:
9
+ def __init__(self) -> None:
10
+ pass
11
+
12
+ def funds(self) -> pl.DataFrame:
13
+ """
14
+ .. raw:: html
15
+
16
+ <div dir="rtl">
17
+ ی سری داده‌یِ از صندوق‌هایِ سرمایه-گذاری رو بهت می‌ده.
18
+ </div>
19
+ """
20
+ url = "https://fund.fipiran.ir/api/v1/fund/dependencygraph"
21
+ r = get(url)
22
+ items = list(filter(lambda x: self._is_gt(x["netAsset"], 0.0), r[0]["items"]))
23
+ validated_r = DependencyGraph.model_validate({"items": items})
24
+ norm_r = normalize_nested_dict(
25
+ [i.model_dump() for i in validated_r.items], "manager"
26
+ )
27
+ return pl.DataFrame(norm_r)
28
+
29
+ def _is_gt(self, x, t: float) -> bool:
30
+ try:
31
+ number = float(x)
32
+ if number > t:
33
+ return True
34
+ return False
35
+ except Exception:
36
+ return False
File without changes
@@ -0,0 +1,55 @@
1
+ import datetime as dt
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, Field, field_validator
5
+
6
+
7
+ class Manager(BaseModel):
8
+ address: Optional[str]
9
+ ceo: Optional[str]
10
+ cfi_id: Optional[int] = Field(alias="cfiId")
11
+ cfiLast_modification_datetime: Optional[str] = Field(
12
+ alias="cfiLastModificationTime"
13
+ )
14
+ is_completed: bool = Field(alias="isCompleted")
15
+ manager_id: Optional[int] = Field(alias="managerId")
16
+ manager_national_no: Optional[str] = Field(alias="managerNationalCode")
17
+ manager_seo_register_no: Optional[str] = Field(alias="managerSeoRegisterNo")
18
+ name: Optional[str]
19
+ national_id: Optional[str] = Field(alias="nationalId")
20
+ register_date: Optional[str] = Field(alias="registerDate")
21
+ register_place: Optional[str] = Field(alias="registerPlace")
22
+ register_place_id: Optional[str] = Field(alias="registerPlaceId")
23
+ registered_capital: Optional[int] = Field(alias="registeredCapital")
24
+ registration_number: Optional[str] = Field(alias="registrationNumber")
25
+ seoRegisterDate: Optional[str] = Field("seo_register_date")
26
+ tel: Optional[str]
27
+ type: Optional[int]
28
+ web_site: Optional[str] = Field(alias="webSite")
29
+
30
+
31
+ class FundItem(BaseModel):
32
+ date: dt.date
33
+ initiation_date: dt.date = Field(alias="initiationDate")
34
+ name: str
35
+ temp_guarantor_name: Optional[str] = Field(alias="tempGuarantorName")
36
+ temp_manager_name: str = Field(alias="tempManagerName")
37
+ type_of_invest: str = Field(alias="typeOfInvest")
38
+ fund_type: int = Field(alias="fundType")
39
+ manager: Manager
40
+ dividend_interval_period: Optional[int] = Field(alias="dividendIntervalPeriod")
41
+ # guarantor: Optional[str]
42
+ fund_size: Optional[int] = Field(alias="fundSize")
43
+ net_asset: Optional[int] = Field(alias="netAsset")
44
+ reg_no: str = Field(alias="regNo")
45
+ issue_nav: Optional[int] = Field(alias="issueNav")
46
+ statistical_nav: Optional[int] = Field(alias="statisticalNav")
47
+ cancel_nav: Optional[int] = Field(alias="cancelNav")
48
+
49
+ @field_validator("date", mode="before")
50
+ def parse_date(cls, value):
51
+ return dt.datetime.fromisoformat(str(value)).date()
52
+
53
+
54
+ class DependencyGraph(BaseModel):
55
+ items: list[FundItem]
@@ -0,0 +1,109 @@
1
+ import datetime as dt
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, field_validator
5
+
6
+ __all__ = ["Stocks", "BalanceSheet", "IncomeStatements", "CashFlow"]
7
+
8
+
9
+ class FSField(BaseModel):
10
+ title: str
11
+ english_title: str
12
+ account: Optional[str] = "-"
13
+ is_parent: bool
14
+ parent: Optional[str]
15
+ index_view: int
16
+ id: str
17
+ sign_neg: bool
18
+ sign_pos: bool
19
+ neg_nature: bool
20
+
21
+
22
+ class FSItems(BaseModel):
23
+ field: FSField
24
+ value: float
25
+
26
+
27
+ class FinancialViewType(BaseModel):
28
+ id: str
29
+
30
+
31
+ class BalanceSheetData(BaseModel):
32
+ date: dt.date
33
+ fiscal_year: dt.date
34
+ announcement_type: str
35
+ financial_view_type: FinancialViewType
36
+ report_id: str
37
+ id: str
38
+ items: list[FSItems]
39
+
40
+ @field_validator("date", "fiscal_year", mode="before")
41
+ def parse_date(cls, value):
42
+ return dt.datetime.strptime(
43
+ str(value),
44
+ "%Y-%m-%dT%H:%M:%S%z",
45
+ ).date()
46
+
47
+
48
+ class BalanceSheet(BaseModel):
49
+ data: list[BalanceSheetData]
50
+
51
+
52
+ class IncomeStatementsData(BaseModel):
53
+ date: dt.date
54
+ fiscal_year: dt.date
55
+ announcement_type_id: str
56
+ financial_view_type_id: str
57
+ report_id: str
58
+ capital: int
59
+ id: str
60
+ items: list[FSItems]
61
+
62
+ @field_validator("date", "fiscal_year", mode="before")
63
+ def parse_date(cls, value):
64
+ return dt.datetime.strptime(
65
+ str(value),
66
+ "%Y-%m-%dT%H:%M:%S%z",
67
+ ).date()
68
+
69
+
70
+ class IncomeStatements(BaseModel):
71
+ data: list[IncomeStatementsData]
72
+
73
+
74
+ class CashFlowField(BaseModel):
75
+ title: str
76
+ english_title: str
77
+ account: Optional[str] = "-"
78
+ is_parent: bool
79
+ index_view: int
80
+ id: str
81
+
82
+
83
+ class CashFlowItems(BaseModel):
84
+ field: CashFlowField
85
+ value: float
86
+
87
+
88
+ class CashFlowData(BaseModel):
89
+ date: dt.date
90
+ fiscal_year: dt.date
91
+ announcement_type_id: str
92
+ financial_view_type_id: str
93
+ report_id: str
94
+ id: str
95
+ items: list[CashFlowItems]
96
+
97
+
98
+ class CashFlow(BaseModel):
99
+ data: list[CashFlowData]
100
+
101
+
102
+ class StocksData(BaseModel):
103
+ name: str
104
+ asset_id: str
105
+ exchange_id: str
106
+
107
+
108
+ class Stocks(BaseModel):
109
+ data: list[StocksData]
@@ -0,0 +1,165 @@
1
+ import datetime as dt
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, Field, field_validator, model_validator
5
+ from pydantic.v1.utils import GetterDict
6
+
7
+
8
+ class MarketWatchOrderBook(BaseModel):
9
+ ob_level: int = Field(alias="n")
10
+ bid_count: int = Field(alias="zmd")
11
+ bid_size: float = Field(alias="qmd")
12
+ bid_price: float = Field(alias="pmd")
13
+ ask_price: float = Field(alias="pmo")
14
+ ask_size: float = Field(alias="qmo")
15
+ ask_count: int = Field(alias="zmo")
16
+
17
+
18
+ class ClientTypeAll(BaseModel):
19
+ ins_code: str = Field(alias="insCode")
20
+ buy_vol_ind: float = Field(alias="buy_I_Volume")
21
+ buy_vol_ins: float = Field(alias="buy_N_Volume")
22
+ buy_count_ind: int = Field(alias="buy_CountI")
23
+ buy_count_ins: int = Field(alias="buy_CountN")
24
+ sell_vol_ind: float = Field(alias="sell_I_Volume")
25
+ sell_vol_ins: float = Field(alias="sell_N_Volume")
26
+ sell_count_ind: int = Field(alias="sell_CountI")
27
+ sell_count_ins: int = Field(alias="sell_CountN")
28
+
29
+
30
+ class MarketWatch(BaseModel):
31
+ ins_code: str = Field(alias="insCode")
32
+ ins_id: str = Field(alias="insID")
33
+ symbol: str = Field(alias="lva")
34
+ name: str = Field(alias="lvc")
35
+ eps: float = Field(alias="eps")
36
+ pe: float = Field(alias="pe")
37
+ bid: float = Field(alias="pmd") #
38
+ ask: float = Field(alias="pmo") #
39
+ open: float = Field(alias="pf")
40
+ high: float = Field(alias="pmx")
41
+ low: float = Field(alias="pmn")
42
+ close: float = Field(alias="pdv")
43
+ final: float = Field(alias="pcl")
44
+ y_final: float = Field(alias="py")
45
+ value: float = Field(alias="qtc")
46
+ volume: float = Field(alias="qtj")
47
+ trade_count: float = Field(alias="ztt")
48
+ max_lim: float = Field(alias="pMax")
49
+ min_lim: float = Field(alias="pMin")
50
+ capital: float = Field(alias="ztd")
51
+ base_volume: float = Field(alias="bv")
52
+ event_time: float = Field(alias="hEven")
53
+ order_book: list[MarketWatchOrderBook] = Field(alias="blDs")
54
+
55
+ @field_validator("pe", mode="before")
56
+ def parce_pe(cls, value):
57
+ try:
58
+ return float(value)
59
+ except ValueError:
60
+ return 0.0
61
+ except TypeError:
62
+ return 0.0
63
+
64
+
65
+ class HistPrice(BaseModel):
66
+ date: dt.date = Field(alias="dEven")
67
+ ins_code: str = Field(alias="insCode")
68
+ open: float = Field(alias="priceFirst")
69
+ high: float = Field(alias="priceMax")
70
+ low: float = Field(alias="priceMin")
71
+ close: float = Field(alias="pDrCotVal")
72
+ final: float = Field(alias="pClosing")
73
+ y_final: float = Field(alias="priceYesterday")
74
+ volume: float = Field(alias="qTotTran5J")
75
+ value: float = Field(alias="qTotCap")
76
+ trade_count: float = Field(alias="zTotTran")
77
+
78
+ @field_validator("date", mode="before")
79
+ def parse_date(cls, value):
80
+ return dt.datetime.strptime(str(value), "%Y%m%d").date()
81
+
82
+
83
+ class EPS(BaseModel):
84
+ eps: Optional[float] = Field(alias="estimatedEPS")
85
+ sector_pe: Optional[float] = Field(alias="sectorPE")
86
+
87
+
88
+ class Sector(BaseModel):
89
+ code: str = Field(alias="cSecVal")
90
+ name: str = Field(alias="lSecVal")
91
+
92
+
93
+ class StaticThreshold(BaseModel):
94
+ min_threshold: float = Field(alias="psGelStaMin")
95
+ max_threshold: float = Field(alias="psGelStaMax")
96
+
97
+
98
+ class InsInfo(BaseModel):
99
+ ins_code: str = Field(alias="insCode")
100
+ ins_id: str = Field(alias="instrumentID")
101
+ isin: str = Field(alias="cIsin")
102
+ symbol: str = Field(alias="lVal18AFC")
103
+ name: str = Field(alias="lVal30")
104
+ name_en: str = Field(alias="lVal18")
105
+ eps: Optional[float]
106
+ sector_pe: Optional[float]
107
+ static_threshold: StaticThreshold = Field(alias="staticThreshold")
108
+ min_week: float = Field(alias="minWeek")
109
+ max_week: float = Field(alias="maxWeek")
110
+ min_year: float = Field(alias="minYear")
111
+ max_year: float = Field(alias="maxYear")
112
+ mean_vol_monthly: float = Field(alias="qTotTran5JAvg")
113
+ pct_float_shares: Optional[str] = Field(alias="kAjCapValCpsIdx")
114
+ base_vol: int = Field(alias="baseVol")
115
+ capital: float = Field(alias="zTitad")
116
+ contract_size: float = Field(alias="contractSize")
117
+ sector_code: str
118
+ sector_name: str
119
+ market_name: str = Field(alias="flowTitle")
120
+ market_code: int = Field(alias="flow")
121
+ market_type: str = Field(alias="cgrValCotTitle")
122
+ group_type: str = Field(alias="cgrValCot")
123
+
124
+ @model_validator(mode="before")
125
+ def flatten_eps_sector(cls, values: GetterDict):
126
+ eps = values.get("eps")
127
+ sector = values.get("sector")
128
+ eps = EPS.model_validate(eps)
129
+ sector = Sector.model_validate(sector)
130
+
131
+ result = {
132
+ "eps": eps.eps,
133
+ "sector_pe": eps.sector_pe,
134
+ "sector_code": sector.code,
135
+ "sector_name": sector.name,
136
+ }
137
+ values.pop("eps")
138
+ values.pop("sector")
139
+ result.update(values)
140
+ return result
141
+
142
+
143
+ class SubSector(BaseModel):
144
+ id: int = Field(alias="cSoSecVal")
145
+ name: str = Field(alias="lSoSecVal")
146
+
147
+
148
+ class InstrumentIdentity(BaseModel):
149
+ isin: str = Field(alias="cIsin")
150
+ instrument_id: str = Field(alias="instrumentID")
151
+ name: str = Field(alias="lSoc30")
152
+ symbol: str = Field(alias="lVal18AFC")
153
+ symbol30: str = Field(alias="lVal30")
154
+ sector: Sector
155
+ sub_sector: SubSector = Field(alias="subSector")
156
+
157
+
158
+ class OrderBook(BaseModel):
159
+ ob_level: int = Field(alias="number")
160
+ bid_count: int = Field(alias="zOrdMeDem")
161
+ bid_volume: float = Field(alias="qTitMeDem")
162
+ bid_price: float = Field(alias="pMeDem")
163
+ ask_price: float = Field(alias="pMeOf")
164
+ ask_volume: float = Field(alias="qTitMeOf")
165
+ ask_count: int = Field(alias="zOrdMeOf")