[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FN7ES886N43NJ8D7DN7F9B":3,"skill-same:01M6FN7ES886N43NJ8D7DN7F9B":58},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":6,"repositoryNo":11,"starsCount":12,"licenseSpdxId":13,"licenseFileUrl":6,"sourceHtmlUrl":14,"categories":15,"keywords":16,"publishedAt":21,"linkOnly":22,"markdownContent":23,"markdownBody":23,"frontMatter":24,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":6,"ownerHtmlUrl":30,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":31,"install":32,"resources":45},"01M6FN7ES886N43NJ8D7DN7F9B","china-market-gateway",null,"kbarbel640-del\u002Fskills","kbarbel640-del","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F255315490?v=4","01M6CJPPQGCCESXMG3K7BBGQ5J","01M6CJPPX2PB2BCZERFVM2C2B3",1,"MIT","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fetherdrake\u002Fchina-market-gateway\u002FSKILL.md",[],[17,18,19,20],"gateway","Market","china","china market gateway","2026-11-10 10:12:30",false,"# China Market Gateway Skill\n\n**Name:** `china-market-gateway`  \n**Description:** Umbrella skill for retrieving Chinese finance data (A-shares, HK, funds, economic data) using Python. Pull stock prices, fund data, market news, and macro indicators from Eastmoney, Sina, CLS, Baidu, and other Chinese sources. Use when researching Chinese equities, mainland stock prices, HK market data, fund performance, or China-related financial news and economic indicators.  \n**License:** MIT  \n**Compatibility:** Requires Python 3.8+, network access to Chinese financial websites. May require proxy for regions with restricted access.  \n\n**Metadata:**\n- **Author:** Etherdrake\n- **Version:** 1.0.2\n- **Supported Markets:**  \n  - A-shares  \n  - HK  \n  - Shanghai  \n  - Shenzhen  \n  - Fund  \n  - Macro\n\n# YuanData - Chinese Finance Data Retrieval (Python)\n\n## When to Use This Skill\n\nUse this skill when you need to:\n\n- Get real-time or historical stock prices for Chinese A-shares (Shanghai\u002FShenzhen)\n- Retrieve Hong Kong (HK) stock data\n- Search for Chinese company financial news\n- Research mainland China market information\n- Access Baidu Gushitong for stock analysis\n- Pull fund data and net asset values\n- Fetch macroeconomic indicators (GDP, CPI, PPI, PMI)\n- Track investment calendars and economic events\n\n## Supported Sources\n\n| Source           | URL Pattern                                                          | Coverage                     |\n|------------------|----------------------------------------------------------------------|------------------------------|\n| Eastmoney        | `https:\u002F\u002Fquote.eastmoney.com\u002F{stockCode}.html`                       | A-shares, HK, indices        |\n| Sina Finance     | `https:\u002F\u002Ffinance.sina.com.cn\u002Frealstock\u002Fcompany\u002F{stockCode}\u002Fnc.shtml` | A-shares, HK, US             |\n| CLS (财联社)        | `https:\u002F\u002Fwww.cls.cn\u002FsearchPage`                                      | Market news, telegraph       |\n| Baidu Gushitong  | `https:\u002F\u002Fgushitong.baidu.com\u002Fstock\u002Fab-{stockCode}`                   | Stock analysis, quotes       |\n| Eastmoney Funds  | `https:\u002F\u002Ffund.eastmoney.com\u002F{fundCode}.html`                         | Fund data                    |\n| Eastmoney Macro  | `https:\u002F\u002Fdatacenter-web.eastmoney.com\u002Fapi\u002Fdata\u002Fv1\u002Fget`               | GDP, CPI, PPI, PMI           |\n\n## Stock Code Formats\n\nChinese stocks use specific prefixes:\n\n- **A-shares (Shanghai):** `sh000001` (SSE), `sh600000` (SSE)\n- **A-shares (Shenzhen):** `sz000001` (SZSE), `sz300000` (ChiNext)\n- **HK stocks:** `hk00001` (HKEX), `hk00700` (Tencent)\n- **US ADRs (for reference):** `usAAPL`\n\n### Examples\n\n| Stock Code     | Company                    | Type       |\n|----------------|----------------------------|------------|\n| `sh000001`     | Shanghai Composite Index   | Index      |\n| `sh600519`     | Kweichow Moutai            | A-share    |\n| `sz000001`     | Ping An Bank               | A-share    |\n| `hk00700`      | Tencent                    | HK         |\n| `hk09660`      | Horizon Robotics           | HK         |\n\n---\n\n# Part 1: Stock Data Retrieval (Python)\n\n## 1. Setup and Dependencies\n\n```python\nimport requests\nfrom bs4 import BeautifulSoup\nimport json\nimport re\nimport time\nfrom datetime import datetime, timedelta\nfrom typing import Optional, Dict, List, Any\nimport logging\n\n# Configure logging\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\nclass YuanData:\n    \"\"\"Chinese Finance Data Retrieval Class\"\"\"\n\n    def __init__(self, proxy: Optional[str] = None):\n        self.session = requests.Session()\n        self.proxy = proxy\n        self.headers = {\n            'User-Agent': 'Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\u002F537.36',\n            'Accept': 'application\u002Fjson, text\u002Fhtml,application\u002Fxhtml+xml',\n            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',\n        }\n        if proxy:\n            self.session.proxies = {'http': proxy, 'https': proxy}\n\n    def _request(self, url: str, headers: Optional[Dict] = None, \n                 timeout: int = 30) -> Optional[Any]:\n        \"\"\"Generic HTTP request handler\"\"\"\n        try:\n            req_headers = {**self.headers, **(headers or {})}\n            response = self.session.get(url, headers=req_headers, timeout=timeout)\n            response.raise_for_status()\n            return response\n        except Exception as e:\n            logger.error(f\"Request failed: {url} - {e}\")\n            return None\n```\n\n## 2. Sina Finance API (Real-Time Stock Data)\n\n```python\nclass SinaStockAPI:\n    \"\"\"Sina Finance Real-Time Stock Data\"\"\"\n\n    BASE_URL = \"http:\u002F\u002Fhq.sinajs.cn\"\n\n    def __init__(self, yuan_data: YuanData):\n        self.parent = yuan_data\n\n    def get_stock_quote(self, stock_code: str) -> Optional[Dict]:\n        \"\"\"\n        Get real-time stock quote from Sina\n\n        Args:\n            stock_code: Stock code (e.g., 'sh600519', 'hk00700')\n\n        Returns:\n            Dict with price, volume, change data\n        \"\"\"\n        # Handle HK stock format (add leading zero)\n        if stock_code.startswith('hk') and len(stock_code) == 6:\n            stock_code = 'hk0' + stock_code[2:]\n\n        timestamp = int(time.time() * 1000)\n        url = f\"{self.BASE_URL}\u002Frn={timestamp}&list={stock_code}\"\n\n        headers = {\n            'Host': 'hq.sinajs.cn',\n            'Referer': 'https:\u002F\u002Ffinance.sina.com.cn\u002F',\n        }\n\n        response = self.parent._request(url, headers=headers)\n        if not response:\n            return None\n\n        # Parse response: var hq_str_sh600519=\"name,open,high,low,close,...\";\n        content = response.text\n        match = re.search(r'hq_str_' + re.escape(stock_code) + r'=\"([^\"]+)\";', content)\n\n        if not match or not match.group(1).strip():\n            logger.warning(f\"No data for {stock_code}\")\n            return None\n\n        data = match.group(1).split(',')\n        return self._parse_stock_data(stock_code, data)\n\n    def _parse_stock_data(self, code: str, data: List[str]) -> Dict:\n        \"\"\"Parse Sina stock data response\"\"\"\n        if code.startswith('sh') or code.startswith('sz'):\n            return {\n                'code': code,\n                'name': data[0],\n                'open': float(data[1]),\n                'pre_close': float(data[2]),\n                'close': float(data[3]),\n                'high': float(data[4]),\n                'low': float(data[5]),\n                'buy_price': float(data[6]),\n                'sell_price': float(data[7]),\n                'volume': int(data[8]),\n                'amount': float(data[9]),\n                'buy_volume': [\n                    int(data[10]), int(data[12]), int(data[14]), \n                    int(data[16]), int(data[18])\n                ],\n                'buy_price': [\n                    float(data[11]), float(data[13]), float(data[15]),\n                    float(data[17]), float(data[19])\n                ],\n                'sell_volume': [\n                    int(data[20]), int(data[22]), int(data[24]),\n                    int(data[26]), int(data[28])\n                ],\n                'sell_price': [\n                    float(data[21]), float(data[23]), float(data[25]),\n                    float(data[27]), float(data[29])\n                ],\n                'date': data[30],\n                'time': data[31],\n            }\n        else:  # HK stock\n            return {\n                'code': code,\n                'name': data[1],\n                'open': float(data[5]),\n                'pre_close': float(data[4]),\n                'close': float(data[3]),\n                'high': float(data[33] or data[32]),\n                'low': float(data[34] or data[33]),\n                'volume': float(data[12].split('.')[0]) if '.' in data[12] else float(data[12]),\n                'amount': float(data[13]) if len(data) > 13 else 0,\n                'date': data[17].replace('\u002F', '-'),\n                'time': data[18].replace(';', ''),\n            }\n\n    def get_multiple_quotes(self, stock_codes: List[str]) -> List[Dict]:\n        \"\"\"Get quotes for multiple stocks (with rate limiting)\"\"\"\n        results = []\n        for code in stock_codes:\n            quote = self.get_stock_quote(code)\n            if quote:\n                results.append(quote)\n            time.sleep(0.1)  # Prevent rate limiting\n        return results\n```\n\n## 3. Tencent Finance API (Alternative Source)\n\n```python\nclass TencentStockAPI:\n    \"\"\"Tencent Finance Real-Time Stock Data\"\"\"\n\n    BASE_URL = \"http:\u002F\u002Fqt.gtimg.cn\"\n\n    def __init__(self, yuan_data: YuanData):\n        self.parent = yuan_data\n\n    def get_stock_quote(self, stock_code: str) -> Optional[Dict]:\n        \"\"\"\n        Get real-time quote from Tencent\n\n        Args:\n            stock_code: e.g., 'sh600519', 'hk00700'\n\n        Returns:\n            Dict with price and metrics\n        \"\"\"\n        if stock_code.startswith('hk'):\n            for code_variant in [f\"r_{stock_code}\", stock_code]:\n                raw_data = self._fetch_tencent(code_variant)\n                if raw_data:\n                    return self._parse_tencent_data(stock_code, raw_data)\n        else:\n            raw_data = self._fetch_tencent(stock_code)\n            if raw_data:\n                return self._parse_tencent_data(stock_code, raw_data)\n        return None\n\n    def _fetch_tencent(self, code: str) -> Optional[str]:\n        \"\"\"Fetch raw data from Tencent API\"\"\"\n        url = f\"{self.BASE_URL}\u002F?q={code}\"\n        headers = {\n            'Host': 'qt.gtimg.cn',\n            'Referer': 'https:\u002F\u002Fgu.qq.com\u002F',\n        }\n        response = self.parent._request(url, headers=headers)\n        return response.text.strip() if response else None\n\n    def _parse_tencent_data(self, code: str, raw_data: str) -> Dict:\n        \"\"\"Parse Tencent response (~ delimited)\"\"\"\n        parts = raw_data.split('~')\n        if len(parts) \u003C 35:\n            raise ValueError(f\"Insufficient data for {code}\")\n\n        return {\n            'code': code,\n            'name': parts[1],\n            'close': float(parts[3]),\n            'pre_close': float(parts[4]),\n            'open': float(parts[5]),\n            'volume': float(parts[6]),\n            'amount': float(parts[7]),\n            'high': float(parts[32] or parts[33]),\n            'low': float(parts[33] or parts[34]),\n            'change_percent': float(parts[31]),\n            'change_amount': float(parts[30]),\n            'turnover_rate': float(parts[38]) if len(parts) > 38 else 0,\n            'market_cap': float(parts[44]) if len(parts) > 44 else 0,\n            'pe_ratio': float(parts[39]) if len(parts) > 39 else 0,\n        }\n```\n\n## 4. Eastmoney Web Scraping\n\n```python\nclass EastmoneyAPI:\n    \"\"\"Eastmoney Web Scraping for Quotes\"\"\"\n\n    def __init__(self, yuan_data: YuanData):\n        self.parent = yuan_data\n\n    def get_quote_page(self, stock_code: str) -> Optional[str]:\n        \"\"\"Fetch HTML page from Eastmoney\"\"\"\n        url = f\"https:\u002F\u002Fquote.eastmoney.com\u002F{stock_code}.html\"\n        response = self.parent._request(url)\n        return response.text if response else None\n\n    def parse_quote(self, html: str) -> Optional[Dict]:\n        \"\"\"Parse quote from Eastmoney HTML\"\"\"\n        soup = BeautifulSoup(html, 'html.parser')\n        try:\n            data = {\n                'price': float(soup.find('span', class_='price').text) if soup.find('span', class_='price') else 0,\n                'change': soup.find('span', class_='change').text if soup.find('span', class_='change') else \"0.00%\",\n                'timestamp': datetime.now().isoformat()\n            }\n            # Extract stats\n            for stat in soup.find_all('td', class_='stat'):\n                label = stat.find('span')\n                value = stat.find('b')\n                if label and value:\n                    data[label.text.strip()] = value.text.strip()\n            return data\n        except Exception as e:\n            logger.error(f\"HTML parsing failed: {e}\")\n            return None\n```\n\n## 5. CLS News API\n\n```python\nclass CLSNewsAPI:\n    \"\"\"CLS (财联社) News and Telegraph API\"\"\"\n\n    BASE_URL = \"https:\u002F\u002Fwww.cls.cn\"\n\n    def __init__(self, yuan_data: YuanData):\n        self.parent = yuan_data\n\n    def search_news(self, keyword: str, search_type: str = \"telegraph\", limit: int = 20) -> List[Dict]:\n        \"\"\"Search news on CLS by keyword\"\"\"\n        response = self.parent._request(\n            f\"{self.BASE_URL}\u002FsearchPage\",\n            params={'keyword': keyword, 'type': search_type}\n        )\n        if not response: return []\n\n        try:\n            soup = BeautifulSoup(response.text, 'html.parser')\n            results = []\n            for item in soup.select('.search-telegraph-list, .subject-interest-list')[:limit]:\n                results.append({\n                    'title': item.get_text(strip=True)[:100],\n                    'source': 'CLS',\n                    'timestamp': datetime.now().isoformat()\n                })\n            return results\n        except Exception as e:\n            logger.error(f\"News parsing failed: {e}\")\n            return []\n\n    def get_telegraph_list(self, limit: int = 50) -> List[Dict]:\n        \"\"\"Get latest market updates (telegraphs)\"\"\"\n        params = {'page': 1, 'page_size': limit}\n        response = self.parent._request(f\"{self.BASE_URL}\u002Fnodeapi\u002FtelegraphList\", params=params)\n        if not response: return []\n\n        try:\n            data = response.json()\n            return data.get(\"data\", {}).get(\"roll_data\", []) if data.get(\"error\") == 0 else []\n        except Exception as e:\n            logger.error(f\"Telegraph fetch failed: {e}\")\n            return []\n```\n\n## 6. Baidu Gushitong API\n\n```python\nclass BaiduGushitongAPI:\n    \"\"\"Baidu Gushitong Stock Analysis\"\"\"\n\n    BASE_URL = \"https:\u002F\u002Fgushitong.baidu.com\"\n\n    def __init__(self, yuan_data: YuanData):\n        self.parent = yuan_data\n\n    def get_stock_page(self, stock_code: str) -> Optional[str]:\n        \"\"\"Retrieve stock analysis page from Baidu\"\"\"\n        url = f\"{self.BASE_URL}\u002Fstock\u002Fab-{stock_code}\"\n        response = self.parent._request(url)\n        return response.text if response else None\n\n    def check_stock_exists(self, stock_code: str) -> bool:\n        \"\"\"Determine if Baidu Gushitong supports the stock\"\"\"\n        url = f\"{self.BASE_URL}\u002Fstock\u002Fab-{stock_code}\"\n        response = self.parent._request(url)\n        return response is not None and response.status_code == 200\n```\n\n---\n\n# Part 2: Fund Data Retrieval (Python)\n\n## 7. Eastmoney Fund API\n\n```python\nclass EastmoneyFundAPI:\n    \"\"\"Eastmoney Fund Data Retrieval\"\"\"\n\n    def __init__(self, yuan_data: YuanData):\n        self.parent = yuan_data\n\n    def get_fund_quote(self, fund_code: str) -> Optional[Dict]:\n        \"\"\"Get latest fund NAV and estimate\"\"\"\n        url = f\"https:\u002F\u002Ffundgz.1234567.com.cn\u002Fjs\u002F{fund_code}.js\"\n        headers = {'Referer': 'https:\u002F\u002Ffund.eastmoney.com\u002F'}\n        response = self.parent._request(url, headers=headers)\n        if not response or 'jsonpgz' not in response.text: return None\n\n        try:\n            json_str = response.text.replace('jsonpgz(', '').rstrip(');')\n            data = json.loads(json_str)\n            return {\n                'code': data.get('fundcode'),\n                'name': data.get('name'),\n                'nav': float(data.get('dwjz', 0)),\n                'nav_date': data.get('jzrq'),\n                'estimated_nav': float(data.get('gsz', 0)),\n                'estimated_nav_time': data.get('gztime'),\n                'growth_rate': float(data.get('zzf', 0)),\n            }\n        except Exception as e:\n            logger.error(f\"Fund data parse failed: {e}\")\n            return None\n\n    def get_fund_details(self, fund_code: str) -> Optional[Dict]:\n        \"\"\"Get detailed fund info via HTML scraping\"\"\"\n        url = f\"https:\u002F\u002Ffund.eastmoney.com\u002F{fund_code}.html\"\n        response = self.parent._request(url)\n        if not response: return None\n\n        soup = BeautifulSoup(response.text, 'html.parser')\n        try:\n            details = {'code': fund_code}\n            title_elem = soup.find('div', class_='fundDetail-tit')\n            if title_elem:\n                details['name'] = title_elem.text.strip()\n\n            info_table = soup.find('table', class_='infoOfFund')\n            if info_table:\n                for row in info_table.find_all('tr'):\n                    cells = row.find_all('td')\n                    text = [c.text.strip() for c in cells]\n                    if '基金类型' in text:\n                        idx = text.index('基金类型'); details['fund_type'] = text[idx + 1]\n                    elif '成立日期' in text:\n                        idx = text.index('成立日期'); details['establishment_date'] = text[idx + 1]\n                    elif '基金经理' in text:\n                        idx = text.index('基金经理'); details['manager'] = text[idx + 1]\n            return details\n        except Exception as e:\n            logger.error(f\"Fund details parse failed: {e}\")\n            return None\n```\n\n---\n\n# Part 3: Economic Data Retrieval (Python)\n\n## 8. Eastmoney Economic Data API\n\n```python\nclass EastmoneyMacroAPI:\n    \"\"\"Eastmoney Macroeconomic Data API\"\"\"\n\n    BASE_URL = \"https:\u002F\u002Fdatacenter-web.eastmoney.com\u002Fapi\u002Fdata\u002Fv1\u002Fget\"\n\n    def __init__(self, yuan_data: YuanData):\n        self.parent = yuan_data\n\n    def _fetch_macro_data(self, params: Dict) -> List[Dict]:\n        \"\"\"Fetch and parse JSONP macro data\"\"\"\n        headers = {\n            'Host': 'datacenter-web.eastmoney.com',\n            'Origin': 'https:\u002F\u002Fdatacenter.eastmoney.com',\n            'Referer': 'https:\u002F\u002Fdata.eastmoney.com\u002Fcjsj\u002F'\n        }\n        response = self.parent._request(self.BASE_URL, headers=headers, params=params)\n        if not response: return []\n\n        try:\n            text = response.text\n            if text.startswith('data('):\n                json_str = re.sub(r'^data\\(|\\);$', '', text)\n                data = json.loads(json_str)\n                return data.get('data', {}).get('result', {}).get('data', [])\n            return []\n        except Exception as e:\n            logger.error(f\"Macro data parse failed: {e}\")\n            return []\n\n    def get_gdp_data(self, page_size: int = 20) -> List[Dict]:\n        \"\"\"Get GDP data\"\"\"\n        params = {\n            'callback': 'data',\n            'columns': 'REPORT_DATE,TIME,DOMESTICL_PRODUCT_BASE,FIRST_PRODUCT_BASE,SECOND_PRODUCT_BASE,THIRD_PRODUCT_BASE,SUM_SAME,FIRST_SAME,SECOND_SAME,THIRD_SAME',\n            'pageNumber': 1,\n            'pageSize': page_size,\n            'sortColumns': 'REPORT_DATE',\n            'sortTypes': -1,\n            'source': 'WEB',\n            'client': 'WEB',\n            'reportName': 'RPT_ECONOMY_GDP',\n        }\n        return self._fetch_macro_data(params)\n\n    def get_cpi_data(self, page_size: int = 20) -> List[Dict]:\n        \"\"\"Get CPI data\"\"\"\n        params = {\n            'callback': 'data',\n            'columns': 'REPORT_DATE,TIME,NATIONAL_SAME,NATIONAL_BASE,NATIONAL_SEQUENTIAL,NATIONAL_ACCUMULATE,CITY_SAME,CITY_BASE,CITY_SEQUENTIAL,CITY_ACCUMULATE,RURAL_SAME,RURAL_BASE,RURAL_SEQUENTIAL,RURAL_ACCUMULATE',\n            'pageNumber': 1,\n            'pageSize': page_size,\n            'sortColumns': 'REPORT_DATE',\n            'sortTypes': -1,\n            'source': 'WEB',\n            'client': 'WEB',\n            'reportName': 'RPT_ECONOMY_CPI',\n        }\n        return self._fetch_macro_data(params)\n\n    def get_ppi_data(self, page_size: int = 20) -> List[Dict]:\n        \"\"\"Get PPI data\"\"\"\n        params = {\n            'callback': 'data',\n            'columns': 'REPORT_DATE,TIME,BASE,BASE_SAME,BASE_ACCUMULATE',\n            'pageNumber': 1,\n            'pageSize': page_size,\n            'sortColumns': 'REPORT_DATE',\n            'sortTypes': -1,\n            'source': 'WEB',\n            'client': 'WEB',\n            'reportName': 'RPT_ECONOMY_PPI',\n        }\n        return self._fetch_macro_data(params)\n\n    def get_pmi_data(self, page_size: int = 20) -> List[Dict]:\n        \"\"\"Get PMI data\"\"\"\n        params = {\n            'callback': 'data',\n            'columns': 'REPORT_DATE,TIME,MAKE_INDEX,MAKE_SAME,NMAKE_INDEX,NMAKE_SAME',\n            'pageNumber': 1,\n            'pageSize': page_size,\n            'sortColumns': 'REPORT_DATE',\n            'sortTypes': -1,\n            'source': 'WEB',\n            'client': 'WEB',\n            'reportName': 'RPT_ECONOMY_PMI',\n        }\n        return self._fetch_macro_data(params)\n```\n\n## 9. Investment Calendar API\n\n```python\nclass InvestmentCalendarAPI:\n    \"\"\"Investment Calendar and Economic Events\"\"\"\n\n    BASE_URL = \"https:\u002F\u002Fapp.jiuyangongshe.com\u002Fjystock-app\u002Fapi\u002Fv1\u002Ftimeline\u002Flist\"\n\n    def __init__(self, yuan_data: YuanData):\n        self.parent = yuan_data\n\n    def get_calendar(self, year_month: Optional[str] = None) -> List[Dict]:\n        \"\"\"Get economic events calendar\"\"\"\n        if not year_month:\n            year_month = datetime.now().strftime('%Y-%m')\n\n        headers = {\n            'Host': 'app.jiuyangongshe.com',\n            'Origin': 'https:\u002F\u002Fwww.jiuyangongshe.com',\n            'Referer': 'https:\u002F\u002Fwww.jiuyangongshe.com\u002F',\n            'Content-Type': 'application\u002Fjson',\n            'token': '1cc6380a05c652b922b3d85124c85473',\n            'platform': '3',\n            'Cookie': 'SESSION=NDZkNDU2ODYtODEwYi00ZGZkLWEyY2ItNjgxYzY4ZWMzZDEy',\n            'timestamp': str(int(time.time() * 1000)),\n        }\n\n        try:\n            response = self.parent.session.post(\n                self.BASE_URL,\n                headers=headers,\n                json={'date': year_month, 'grade': '0'},\n                timeout=30\n            )\n            return response.json().get('data', []) if response.status_code == 200 else []\n        except Exception as e:\n            logger.error(f\"Calendar fetch failed: {e}\")\n            return []\n```\n\n---\n\n# Part 4: Unified Data Access Class\n\n## 10. YuanData Main Class\n\n```python\nclass YuanData:\n    \"\"\"Unified Chinese Finance Data Access Class\"\"\"\n\n    def __init__(self, proxy: Optional[str] = None):\n        self.proxy = proxy\n        self.session = requests.Session()\n        self.headers = {\n            'User-Agent': 'Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\u002F537.36',\n            'Accept': 'application\u002Fjson, text\u002Fhtml',\n        }\n        if proxy:\n            self.session.proxies = {'http': proxy, 'https': proxy}\n\n        # Initialize API clients\n        self.stock = _StockAPI(self)\n        self.fund = _FundAPI(self)\n        self.macro = _MacroAPI(self)\n        self.news = _NewsAPI(self)\n\n    def _request(self, url: str, headers: Optional[Dict] = None,\n                 params: Optional[Dict] = None, timeout: int = 30) -> Optional[Any]:\n        \"\"\"Generic HTTP request\"\"\"\n        try:\n            final_headers = {**self.headers, **(headers or {})}\n            response = self.session.get(url, headers=final_headers, params=params, timeout=timeout)\n            response.raise_for_status()\n            return response\n        except Exception as e:\n            logger.error(f\"Request failed: {url} - {e}\")\n            return None\n\n# Internal API wrappers\nclass _StockAPI:\n    def __init__(self, parent): self.parent = parent\n    def get_quote(self, code: str) -> Optional[Dict]:\n        url = f\"http:\u002F\u002Fhq.sinajs.cn\u002Flist={code}\"\n        headers = {'Host': 'hq.sinajs.cn', 'Referer': 'https:\u002F\u002Ffinance.sina.com.cn\u002F'}\n        response = self.parent._request(url, headers=headers)\n        return {'code': code, 'source': 'sina'} if response else None\n\nclass _FundAPI:\n    def __init__(self, parent): self.parent = parent\n    def get_quote(self, code: str) -> Optional[Dict]:\n        url = f\"https:\u002F\u002Ffundgz.1234567.com.cn\u002Fjs\u002F{code}.js\"\n        response = self.parent._request(url, headers={'Referer': 'https:\u002F\u002Ffund.eastmoney.com\u002F'})\n        return {'code': code, 'source': 'fund'} if response else None\n\nclass _MacroAPI:\n    def __init__(self, parent): self.parent = parent\n    def get_gdp(self) -> List[Dict]:\n        return []\n    def get_cpi(self) -> List[Dict]:\n        return []\n\nclass _NewsAPI:\n    def __init__(self, parent): self.parent = parent\n    def search(self, keyword: str) -> List[Dict]:\n        return []\n\n# Convenience functions\ndef get_stock_price(stock_code: str, proxy: Optional[str] = None) -> Optional[Dict]:\n    \"\"\"Get real-time stock price\"\"\"\n    data = YuanData(proxy)\n    return data.stock.get_quote(stock_code)\n\ndef get_fund_nav(fund_code: str, proxy: Optional[str] = None) -> Optional[Dict]:\n    \"\"\"Get fund NAV\"\"\"\n    data = YuanData(proxy)\n    return data.fund.get_quote(fund_code)\n\ndef get_gdp_data(proxy: Optional[str] = None) -> List[Dict]:\n    \"\"\"Get GDP data\"\"\"\n    data = YuanData(proxy)\n    return data.macro.get_gdp()\n\ndef get_cpi_data(proxy: Optional[str] = None) -> List[Dict]:\n    \"\"\"Get CPI data\"\"\"\n    data = YuanData(proxy)\n    return data.macro.get_cpi()\n```\n\n---\n\n# Part 5: Handling Tickers That Don't Return Data\n\n## 11. Troubleshooting Guide (Python)\n\n```python\nclass DataTroubleshooter:\n    \"\"\"Diagnose why tickers return no data\"\"\"\n\n    @staticmethod\n    def check_hk_format(stock_code: str) -> str:\n        \"\"\"Fix HK stock format (e.g., 'hk2259' → 'hk02259')\"\"\"\n        if stock_code.startswith('hk') and len(stock_code) == 6:\n            return 'hk0' + stock_code[2:]\n        return stock_code\n\n    @staticmethod\n    def check_baidu_exists(stock_code: str, proxy: Optional[str] = None) -> bool:\n        \"\"\"Verify Baidu Gushitong has data for this stock\"\"\"\n        url = f\"https:\u002F\u002Fgushitong.baidu.com\u002Fstock\u002Fab-{stock_code}\"\n        data = YuanData(proxy)\n        response = data._request(url)\n        return response is not None and response.status_code == 200\n\ndef troubleshoot_ticker(stock_code: str, proxy: Optional[str] = None) -> Dict:\n    \"\"\"Diagnose missing ticker data\"\"\"\n    results = {\n        'original_code': stock_code,\n        'tests': []\n    }\n\n    # Format check\n    corrected = DataTroubleshooter.check_hk_format(stock_code)\n    results['corrected_code'] = corrected\n    results['tests'].append({\n        'test': 'format_correction',\n        'input': stock_code,\n        'output': corrected,\n        'changed': stock_code != corrected\n    })\n\n    # Sina test\n    sina_success = get_stock_price(corrected, proxy) is not None\n    results['tests'].append({\n        'test': 'sina_api',\n        'result': sina_success\n    })\n\n    # Baidu site check\n    baidu_available = DataTroubleshooter.check_baidu_exists(corrected, proxy)\n    results['tests'].append({\n        'test': 'baidu_page_exists',\n        'result': baidu_available\n    })\n\n    # Recommendation\n    if sina_success:\n        results['recommendation'] = 'USE_CORRECTED_CODE'\n    elif baidu_available:\n        results['recommendation'] = 'CHECK_MANUALLY'\n    else:\n        results['recommendation'] = 'INACTIVE_OR_INVALID'\n\n    return results\n```\n\n---\n\n# Part 6: Common Stock Code Examples\n\n| Company               | A-Share Code | HK Code  | Industry         |\n|-----------------------|--------------|----------|------------------|\n| Kweichow Moutai       | sh600519     | -        | Liquor           |\n| Tencent               | -            | hk00700  | Internet         |\n| Alibaba               | sh9988       | hk9988   | E-commerce       |\n| Meituan                 | sh3690       | hk3690   | Food Delivery    |\n| Ping An               | sh601318     | hk2318   | Insurance        |\n| BYD                   | sh002594     | hk1211   | Electric Vehicles |\n| China Merchants Bank  | sh600036     | hk3968   | Banking          |\n| Industrial Bank       | sh601166     | -        | Banking          |\n\n---\n\n# Part 7: Important Notes\n\n### Time Zone\n\n- China Standard Time (CST): **UTC+8**\n- Trading Hours:\n  - Morning: **9:30–11:30**\n  - Afternoon: **13:00–15:00**\n- Lunch Break: **11:30–13:00**\n\n### Currency\n\n- **A-shares:** CNY (RMB)\n- **HK stocks:** HKD\n- Approx rate: **1 HKD ≈ 0.89 CNY**\n\n### Market Holidays\n\nClosed on:\n- Weekends (Saturday–Sunday)\n- Public holidays: **Chinese New Year, National Day (Oct 1), Labor Day (May 1)**\n\n### Proxy Requirements\n\n- Consider using a **CN-based proxy or VPS** when accessing from outside China\n- Some sites block non-Chinese IPs\n\n---\n\n# Part 8: Usage Examples\n\n```python\n# Initialize with optional proxy\ndata = YuanData(proxy=\"http:\u002F\u002Flocalhost:10809\")\n\n# Get A-share quote (Kweichow Moutai)\nquote = data.stock.get_quote(\"sh600519\")\nprint(f\"Moutai: {quote}\")\n\n# Get HK quote (Tencent)\nhk_quote = data.stock.get_quote(\"hk00700\")\nprint(f\"Tencent: {hk_quote}\")\n\n# Get fund NAV\nfund = data.fund.get_quote(\"161039\")\nprint(f\"Fund NAV: {fund}\")\n\n# Get GDP data\ngdp = data.macro.get_gdp()\nprint(f\"GDP: {gdp}\")\n\n# Search news\nnews = data.news.search(\"茅台\")\nprint(f\"News: {news}\")\n\n# Troubleshoot ticker\nresult = troubleshoot_ticker(\"hk2259\")\nprint(f\"Troubleshoot: {result}\")\n```\n\n",{},"main","e7e336ac628c3e3bd771aff1aaa469c93778f94a","skills\u002Fetherdrake\u002Fchina-market-gateway",0,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del","2026-08-23 22:39:37",{"source":7,"skillName":5,"commands":33,"prompt":43,"zipAvailable":44},[34,37,40],{"tool":35,"command":36},"npx","npx skills add kbarbel640-del\u002Fskills --skill china-market-gateway",{"tool":38,"command":39},"bunx","bunx skills add kbarbel640-del\u002Fskills --skill china-market-gateway",{"tool":41,"command":42},"pnpm","pnpm dlx skills add kbarbel640-del\u002Fskills --skill china-market-gateway","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fetherdrake\u002Fchina-market-gateway\u002FSKILL.md",true,[46,52],{"path":47,"resourceType":48,"resourceTypeDesc":49,"sizeBytes":50,"sourceHtmlUrl":51},"__init__.py","SCRIPT","脚本",10188,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fetherdrake\u002Fchina-market-gateway\u002F__init__.py",{"path":53,"resourceType":54,"resourceTypeDesc":55,"sizeBytes":56,"sourceHtmlUrl":57},"_meta.json","REFERENCE","参考文档",474,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fetherdrake\u002Fchina-market-gateway\u002F_meta.json",[59,90,119,140,146,166],{"skillNo":60,"name":61,"nameZh":6,"description":62,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":6,"repositoryNo":11,"starsCount":12,"licenseSpdxId":13,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":70,"publishedAt":21},"01M6G8J55967D6281ACMKAKTEQ","crowd-prompting","A marketplace where AI agents improve prompts, system instructions, tool descriptions, and other text-based content with domain expertise from real-world operations — and earn tokens for valuable contributions.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzzadrian\u002Fcrowd-prompting\u002FSKILL.md",[65],{"categoryNo":66,"categoryName":67,"taxonomyType":68,"taxonomyTypeDesc":69},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89],"crowd prompting","prompting","api","with","tokens","domain","world","prompts","operations","instructions","text","tool","system","improve","productivity","marketplace","https","content","ai agents",{"skillNo":91,"name":92,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":6,"repositoryNo":11,"starsCount":12,"licenseSpdxId":13,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":101,"publishedAt":21},"01M6G8J0PKPAYVET6BWE8W4C26","dilemm-ai","Compete in DilemmAI, the prisoner's dilemma AI arena at dilemm.ai. Use when an OpenClaw agent wants to create an account, design and submit strategy prompts for their bot, enter matchmaking, analyze historical matches and leaderboards, and iterate on bot strategy. Requires headless browser automation (no API available yet).","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzyori\u002Fdilemm-ai\u002FSKILL.md",[96],{"categoryNo":97,"categoryName":98,"taxonomyType":99,"taxonomyTypeDesc":100},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[102,73,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,78,118],"dilemm ai","arena","analyze","browser","openclaw agent","create","automation","browser automation","bot","openclaw","design","strategy","headless","compete","submit","matchmaking","use",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":6,"repositoryNo":11,"starsCount":12,"licenseSpdxId":13,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":128,"publishedAt":21},"01M6G8HWAF3K9SW7NP3Z83CPJ6","arxiv-paper-reviews","Interact with arXiv Crawler API to fetch papers, read reviews, and submit comments. Use when working with arXiv papers, fetching paper lists by date\u002Fcategory\u002Finterest, viewing paper details with comments, or submitting paper reviews via API at http:\u002F\u002F150.158.152.82:8000.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Fweak-accept\u002FSKILL.md",[125],{"categoryNo":126,"categoryName":127,"taxonomyType":99,"taxonomyTypeDesc":100},"01JBSEEDCAT000000000000021","资料检索与研究",[129,130,131,132,133,134,135,74,136,116,118,137,73,138,139],"arxiv paper reviews","reviews","arxiv","paper","crawler","papers","comments","fetch","read","http","via",{"skillNo":141,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":6,"repositoryNo":11,"starsCount":12,"licenseSpdxId":13,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":145,"publishedAt":21},"01M6G8HQJ7N7WMY6YV7D7SSJ16","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Farxiv-paper-reviews\u002FSKILL.md",[144],{"categoryNo":126,"categoryName":127,"taxonomyType":99,"taxonomyTypeDesc":100},[132,131,130,129,139,134,135,74,133,116,118,136,137,73,138],{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":6,"repositoryNo":11,"starsCount":12,"licenseSpdxId":13,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":152,"publishedAt":21},"01M6G8HM95Y64JNVFC2HN4E2BG","git-summary","Get a quick summary of the current Git repository including status, recent commits, branches, and contributors.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzweack\u002Fgit-summary\u002FSKILL.md",[],[153,154,155,156,157,158,159,160,161,162,163,164,165],"git","summary","git summary","commits","repository","win32","status","linux","contributors","true","quick","get","branches",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":6,"repositoryNo":11,"starsCount":12,"licenseSpdxId":13,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":176,"publishedAt":21},"01M6G8HGEGF05CNEJCGVYFSC4R","agent-constitution","Interact with AgentConstitution governance contracts on Base Sepolia. Check compliance, read rules, log actions, query governance state.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fztsalexey\u002Fagent-constitution\u002FSKILL.md",[172,173],{"categoryNo":97,"categoryName":98,"taxonomyType":99,"taxonomyTypeDesc":100},{"categoryNo":174,"categoryName":175,"taxonomyType":68,"taxonomyTypeDesc":69},"01JBSEEDCAT000000000000037","律师与法务",[177,178,179,180,74,181,182,25,183,137,184,185,186,187,188,87,189,190,191],"agent constitution","constitution","contracts","tree","query","base","log","check","Rules","projects","compliance","actions","state","governance","github"]