camphong24032002 commited on
Commit
048da70
·
1 Parent(s): a754350

Update rsi and ichimoku api

Browse files
models/ichimoku.py CHANGED
@@ -3,11 +3,15 @@ from pydantic import BaseModel, root_validator
3
 
4
  class IchimokuPayload(BaseModel):
5
  symbol: str
6
- count_back: int = 365
7
- type: str = "stock"
 
 
 
 
8
 
9
  @root_validator
10
  def validate_dates(cls, values):
11
- if values['type'] not in ["index", "stock"]:
12
  raise ValueError('type should be index or stock')
13
  return values
 
3
 
4
  class IchimokuPayload(BaseModel):
5
  symbol: str
6
+ count_back: int = 200
7
+ symbol_type: str = "stock"
8
+ conversion_period: int = 9
9
+ base_period: int = 26
10
+ span_b_period: int = 52
11
+ displacement: int = 26
12
 
13
  @root_validator
14
  def validate_dates(cls, values):
15
+ if values['symbol_type'] not in ["index", "stock"]:
16
  raise ValueError('type should be index or stock')
17
  return values
models/price.py CHANGED
@@ -4,10 +4,10 @@ from pydantic import BaseModel, root_validator
4
  class PricePayload(BaseModel):
5
  symbol: str
6
  count_back: int = 365
7
- type: str = "stock"
8
 
9
  @root_validator
10
  def validate_dates(cls, values):
11
- if values['type'] not in ["index", "stock"]:
12
  raise ValueError('type should be index or stock')
13
  return values
 
4
  class PricePayload(BaseModel):
5
  symbol: str
6
  count_back: int = 365
7
+ symbol_type: str = "stock"
8
 
9
  @root_validator
10
  def validate_dates(cls, values):
11
+ if values['symbol_type'] not in ["index", "stock"]:
12
  raise ValueError('type should be index or stock')
13
  return values
models/rsi.py CHANGED
@@ -3,7 +3,6 @@ from pydantic import BaseModel
3
 
4
  class RSIPayload(BaseModel):
5
  symbol: str
6
- range_selector: str = "1y"
7
  periods: int = 14
8
  smooth_k: int = 3
9
  smooth_d: int = 3
 
3
 
4
  class RSIPayload(BaseModel):
5
  symbol: str
 
6
  periods: int = 14
7
  smooth_k: int = 3
8
  smooth_d: int = 3
routes/data.py CHANGED
@@ -17,7 +17,7 @@ router = APIRouter()
17
  async def get_price_data(payload: PricePayload) -> Sequence[dict]:
18
  price_df = Indicator.get_price(payload.symbol,
19
  payload.count_back,
20
- payload.type)
21
  return json.loads(price_df.to_json(orient="records"))
22
 
23
 
@@ -29,7 +29,6 @@ async def get_price_data(payload: PricePayload) -> Sequence[dict]:
29
  async def get_rsi_data(payload: RSIPayload) -> Sequence[dict]:
30
  rsi_df = Indicator.get_rsi(
31
  payload.symbol,
32
- payload.range_selector,
33
  payload.periods,
34
  payload.smooth_k,
35
  payload.smooth_d
@@ -45,6 +44,10 @@ async def get_rsi_data(payload: RSIPayload) -> Sequence[dict]:
45
  async def get_ichimoku_data(payload: IchimokuPayload) -> Sequence[dict]:
46
  price_df = Indicator.get_price(payload.symbol,
47
  payload.count_back,
48
- payload.type)
49
- ichimoku_df = Indicator.get_ichimoku_cloud(price_df)
 
 
 
 
50
  return json.loads(ichimoku_df.to_json(orient="records"))
 
17
  async def get_price_data(payload: PricePayload) -> Sequence[dict]:
18
  price_df = Indicator.get_price(payload.symbol,
19
  payload.count_back,
20
+ payload.symbol_type)
21
  return json.loads(price_df.to_json(orient="records"))
22
 
23
 
 
29
  async def get_rsi_data(payload: RSIPayload) -> Sequence[dict]:
30
  rsi_df = Indicator.get_rsi(
31
  payload.symbol,
 
32
  payload.periods,
33
  payload.smooth_k,
34
  payload.smooth_d
 
44
  async def get_ichimoku_data(payload: IchimokuPayload) -> Sequence[dict]:
45
  price_df = Indicator.get_price(payload.symbol,
46
  payload.count_back,
47
+ payload.symbol_type)
48
+ ichimoku_df = Indicator.get_ichimoku_cloud(price_df,
49
+ payload.conversion_period,
50
+ payload.base_period,
51
+ payload.span_b_period,
52
+ payload.displacement)
53
  return json.loads(ichimoku_df.to_json(orient="records"))
services/indicator.py CHANGED
@@ -1,10 +1,11 @@
1
  import requests
2
- import json
3
  from datetime import datetime, timedelta
4
  import pandas as pd
5
  import numpy as np
6
- from vnstock import longterm_ohlc_data
7
- from .utils import Utility
 
 
8
 
9
  PREFIX = "https://www.hsx.vn/Modules/Chart/StaticChart/"
10
  TIME = {"1m": 2, "3m": 3, "6m": 4, "1y": 5, "2y": 6, "5y": 7}
@@ -24,49 +25,84 @@ class Indicator:
24
 
25
  @staticmethod
26
  def get_price(symbol: str,
27
- count_back: int = 365,
28
- type: str = "stock",) -> pd.DataFrame:
29
  resolution = "D"
30
  end_date = datetime.now()
31
  delta = timedelta(days=count_back)
32
  start_date = end_date - delta
33
  start_date = datetime.strftime(start_date, '%Y-%m-%d')
34
  end_date = datetime.strftime(end_date, '%Y-%m-%d')
35
- return longterm_ohlc_data(symbol, start_date, end_date,
36
- resolution, type).reset_index()
 
 
 
 
 
 
37
 
38
  @staticmethod
39
  def get_rsi(
40
  symbol: str,
41
- range_selector: str = "1y",
42
  periods: int = 14,
43
  smooth_k: int = 3,
44
  smooth_d: int = 3,
45
  ) -> pd.DataFrame:
46
- range_selector = TIME[range_selector]
47
- params = {
48
- "stockSymbol": symbol,
49
- "rangeSelector": range_selector,
50
- "period": periods,
51
- }
52
- lst_param = []
53
- for key, value in params.items():
54
- lst_param.append(f"{key}={value}")
55
- url = PREFIX + INDICATORS["RSI"] + "?" + "&".join(lst_param)
56
- response = requests.get(url)
57
- data = json.loads(response.text)
58
- rsi_df = pd.DataFrame(data["SeriesColection"][0]["Points"])
59
- rsi_df["time"] = \
60
- rsi_df["Time"].apply(lambda x: Utility.ts_to_date(x/1000))
61
- rsi_df["rsi"] = rsi_df["Value"].apply(lambda x: x[0])
62
- rsi_df = rsi_df[["date", "rsi"]]
63
- rsi_df["stoch_rsi"] = Indicator.stoch_rsi(rsi_df["rsi"], periods)
64
- rsi_df["stoch_rsi_smooth_k"] = \
65
- Indicator.stoch_rsi_smooth_k(rsi_df["stoch_rsi"], smooth_k)
66
- rsi_df["stoch_rsi_smooth_d"] = Indicator.stoch_rsi_smooth_d(
67
- rsi_df["stoch_rsi_smooth_k"], smooth_d
68
- )
69
- return rsi_df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
  @staticmethod
72
  def stoch_rsi(rsi: pd.Series, periods: int = 14) -> pd.Series:
 
1
  import requests
 
2
  from datetime import datetime, timedelta
3
  import pandas as pd
4
  import numpy as np
5
+ from vnstock import longterm_ohlc_data, stock_historical_data, price_board
6
+ from pymongo import MongoClient, ASCENDING, DESCENDING
7
+ from utils.config import DATE_FORMAT
8
+ import os
9
 
10
  PREFIX = "https://www.hsx.vn/Modules/Chart/StaticChart/"
11
  TIME = {"1m": 2, "3m": 3, "6m": 4, "1y": 5, "2y": 6, "5y": 7}
 
25
 
26
  @staticmethod
27
  def get_price(symbol: str,
28
+ count_back: int = 100,
29
+ symbol_type: str = "stock",) -> pd.DataFrame:
30
  resolution = "D"
31
  end_date = datetime.now()
32
  delta = timedelta(days=count_back)
33
  start_date = end_date - delta
34
  start_date = datetime.strftime(start_date, '%Y-%m-%d')
35
  end_date = datetime.strftime(end_date, '%Y-%m-%d')
36
+ df = longterm_ohlc_data(symbol, start_date, end_date,
37
+ resolution, symbol_type).reset_index(drop=True)
38
+ df[['open', 'high', 'low', 'close']] = \
39
+ df[['open', 'high', 'low', 'close']] * 1000
40
+ # convert open, high, low, close to int
41
+ df[['open', 'high', 'low', 'close']] = \
42
+ df[['open', 'high', 'low', 'close']].astype(int)
43
+ return df
44
 
45
  @staticmethod
46
  def get_rsi(
47
  symbol: str,
 
48
  periods: int = 14,
49
  smooth_k: int = 3,
50
  smooth_d: int = 3,
51
  ) -> pd.DataFrame:
52
+ try:
53
+ symbol = symbol.upper()
54
+ uri = os.environ.get("MONGODB_URI")
55
+ client = MongoClient(uri)
56
+ database = client.get_database("data")
57
+ collection = database.get_collection("rsi")
58
+ datetime_now = datetime.utcnow()
59
+ hour = datetime_now.hour
60
+ weekday = datetime_now.weekday()
61
+ error = False
62
+ if weekday < 5 and hour >= 12: # Check if data is updated
63
+ newest_record = collection.find_one(sort=[("_id", DESCENDING)])
64
+ delta = timedelta(days=20)
65
+ start_date = datetime_now - delta
66
+ start_date = start_date.strftime(DATE_FORMAT)
67
+ end_date = datetime_now.strftime(DATE_FORMAT)
68
+ tmp_df = stock_historical_data("MBB", start_date, end_date)
69
+ last_date = str(tmp_df["time"].iloc[-1])
70
+ if newest_record["time"] != last_date:
71
+ try:
72
+ lst_symbols = list(newest_record.keys())[2:]
73
+ record = {}
74
+ record["time"] = last_date
75
+ for s in lst_symbols:
76
+ url = PREFIX + INDICATORS["RSI"] + \
77
+ f"?stockSymbol={symbol}\
78
+ &rangeSelector=0\
79
+ &periods={periods}"
80
+ data = requests.get(url).json()
81
+ lst_rsi = data["SeriesColection"][0]["Points"]
82
+ record[s] = lst_rsi[-1]["Value"][0]
83
+ collection.find_one_and_delete(
84
+ sort=[("_id", ASCENDING)])
85
+ collection.insert_one(record)
86
+ print("Updated data")
87
+ except Exception:
88
+ error = True
89
+ records = list(collection.find())
90
+ record_df = pd.DataFrame(records).drop(columns=["_id"])
91
+ record_df = \
92
+ record_df[["time", symbol]].rename(columns={symbol: "rsi"})
93
+ if error:
94
+ new_df = price_board(symbol)
95
+ record_df.loc[len(record_df)] = new_df[["time", "RSI"]].values
96
+ record_df["stoch_rsi"] = \
97
+ Indicator.stoch_rsi(record_df["rsi"], periods)
98
+ record_df["stoch_rsi_smooth_k"] = \
99
+ Indicator.stoch_rsi_smooth_k(record_df["stoch_rsi"], smooth_k)
100
+ record_df["stoch_rsi_smooth_d"] = Indicator.stoch_rsi_smooth_d(
101
+ record_df["stoch_rsi_smooth_k"], smooth_d
102
+ )
103
+ return record_df
104
+ except Exception:
105
+ return None
106
 
107
  @staticmethod
108
  def stoch_rsi(rsi: pd.Series, periods: int = 14) -> pd.Series: