Skip to content

Commit d22052e

Browse files
committed
feat(market_watch_init): use int64
index_col does not work with Int64 datatype, see: pandas-dev/pandas#44835
1 parent 1e77109 commit d22052e

File tree

2 files changed

+36
-20
lines changed

2 files changed

+36
-20
lines changed

test/test_tsetmc.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -303,26 +303,39 @@ def test_fmelli_instant():
303303

304304
@patch_get_content('MarketWatchInit.aspx')
305305
def test_market_watch_init():
306-
df = market_watch_init()['prices']
307-
assert df.dtypes.to_dict() == {
306+
dtypes = {
308307
'heven': 'int64', 'pf': 'int64', 'pc': 'int64'
309308
, 'pl': 'int64', 'tno': 'int64', 'tvol': 'int64'
310309
, 'tval': 'int64', 'pmin': 'int64', 'pmax': 'int64'
311310
, 'py': 'int64', 'eps': 'float64', 'bvol': 'int64'
312311
, 'visitcount': 'int64', 'flow': 'int64'
313312
, 'cs': 'int64', 'tmax': 'float64', 'tmin': 'float64'
314-
, 'z': 'int64', 'yval': 'int64', 'pd1': 'Int64'
315-
, 'po1': 'Int64', 'qd1': 'Int64', 'qo1': 'Int64'
316-
, 'zd1': 'Int64', 'zo1': 'Int64', 'pd2': 'Int64'
317-
, 'po2': 'Int64', 'qd2': 'Int64', 'qo2': 'Int64'
318-
, 'zd2': 'Int64', 'zo2': 'Int64', 'pd3': 'Int64'
319-
, 'po3': 'Int64', 'qd3': 'Int64', 'qo3': 'Int64'
320-
, 'zd3': 'Int64', 'zo3': 'Int64'}
321-
index = df.index
322-
assert index.names == ['ins_code', 'isin', 'l18', 'l30']
323-
assert index.dtype == 'O'
324-
# in pandas 1.3 there will be no need for `.to_frame()`
325-
assert index.to_frame().dtypes.to_list() == ['int64', 'O', 'O', 'O']
313+
, 'z': 'int64', 'yval': 'int64'}
314+
315+
mwi = market_watch_init(join=False, market_state=False)
316+
assert mwi['prices'].dtypes.to_dict() == dtypes
317+
assert mwi['best_limits'].index.names == ['ins_code', 'row']
318+
assert 'market_state' not in mwi
319+
320+
mwi = market_watch_init(market_state=True)
321+
prices = mwi['prices']
322+
assert 'market_state' in mwi
323+
assert 'best_limits' in mwi
324+
assert prices.dtypes.to_dict() == {
325+
**dtypes, 'pd1': 'int64'
326+
, 'po1': 'int64', 'qd1': 'int64', 'qo1': 'int64'
327+
, 'zd1': 'int64', 'zo1': 'int64', 'pd2': 'int64'
328+
, 'po2': 'int64', 'qd2': 'int64', 'qo2': 'int64'
329+
, 'zd2': 'int64', 'zo2': 'int64', 'pd3': 'int64'
330+
, 'po3': 'int64', 'qd3': 'int64', 'qo3': 'int64'
331+
, 'zd3': 'int64', 'zo3': 'int64'}
332+
assert prices.index.dtypes.to_dict() == {
333+
'ins_code': 'int64', 'isin': 'O', 'l18': 'O', 'l30': 'O'}
334+
335+
mwi = market_watch_init(prices=False, market_state=False)
336+
assert 'prices' not in mwi
337+
assert mwi['best_limits'].index.dtypes.to_dict() == {
338+
'ins_code': 'int64', 'row': 'int64'}
326339

327340

328341
@patch_get_content('ClosingPriceAll.aspx')

tsetmc/_tsetmc.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ class IntraDay(TypedDict, total=False):
125125
best_limits: DataFrame
126126

127127

128+
PRICE_INDEX_COLS = ['ins_code', 'isin', 'l18', 'l30']
129+
130+
128131
class Instrument:
129132

130133
__slots__ = 'code', '_l18', '_l30', '_cisin'
@@ -516,7 +519,7 @@ def adjustments(self) -> DataFrame:
516519

517520

518521
def market_watch_init(
519-
market_state=False, prices=True, best_limits=True, join=True
522+
*, market_state=True, prices=True, best_limits=True, join=True
520523
) -> MarketWatchInit:
521524
"""Return the market status which are the info used in creating filters.
522525
@@ -534,7 +537,7 @@ def market_watch_init(
534537
(it's the time of last transaction in HHMMSS format)
535538
"""
536539
text = fa_norm_text('http://tsetmc.com/tsev2/data/MarketWatchInit.aspx?h=0&r=0')
537-
_, index_data, states, price_rows, _ = text.split('@')
540+
_, market_state_str, states, price_rows, _ = text.split('@')
538541
result = {}
539542
if prices:
540543
result['prices'] = price_df = read_csv(
@@ -544,25 +547,25 @@ def market_watch_init(
544547
'ins_code', 'isin', 'l18', 'l30', 'heven', 'pf', 'pc', 'pl',
545548
'tno', 'tvol', 'tval', 'pmin', 'pmax', 'py', 'eps', 'bvol',
546549
'visitcount' , 'flow', 'cs', 'tmax', 'tmin', 'z', 'yval'),
547-
index_col=['ins_code', 'isin', 'l18', 'l30'])
550+
index_col=PRICE_INDEX_COLS)
548551
if best_limits:
549552
result['best_limits'] = best_limits_df = read_csv(
550553
StringIO(price_rows), lineterminator=';', names=(
551554
'ins_code', 'row', 'zo', 'zd', 'pd', 'po', 'qd', 'qo'),
552-
dtype='Int64')
555+
dtype='int64', index_col=('ins_code', 'row'))
556+
# best_limits_df.set_index(['ins_code', 'row'], inplace=True)
553557
if join and prices and best_limits:
554558
# merge multiple rows sharing the same `row` number into one row.
555559
# a fascinating solution from https://stackoverflow.com/a/53563551/2705757
556560
# noinspection PyUnboundLocalVariable
557-
best_limits_df.set_index(['ins_code', 'row'], inplace=True)
558561
best_limits_df = best_limits_df.unstack(fill_value=0).sort_index(axis=1, level=1)
559562
best_limits_df.columns = [f'{c}{i}' for c, i in best_limits_df.columns]
560563
# noinspection PyUnboundLocalVariable
561564
joined = best_limits_df.join(price_df)
562565
# joined_df.index = to_numeric(joined_df.index, downcast='unsigned')
563566
result['prices'] = joined
564567
if market_state:
565-
result['market_state'] = _parse_market_state(index_data)
568+
result['market_state'] = _parse_market_state(market_state_str)
566569
return result
567570

568571

0 commit comments

Comments
 (0)