{"id":51059130,"url":"https://github.com/erishen/investkit_utils","last_synced_at":"2026-06-23T00:01:36.772Z","repository":{"id":364804500,"uuid":"1228442919","full_name":"erishen/investkit_utils","owner":"erishen","description":"Shared utilities library — config, logging, database, and type definitions","archived":false,"fork":false,"pushed_at":"2026-06-14T14:14:43.000Z","size":124,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-14T16:39:34.530Z","etag":null,"topics":["configuration","logging","python","shared-library","utilities"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/erishen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-04T02:47:24.000Z","updated_at":"2026-06-14T14:14:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/erishen/investkit_utils","commit_stats":null,"previous_names":["erishen/investkit_utils"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/erishen/investkit_utils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erishen%2Finvestkit_utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erishen%2Finvestkit_utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erishen%2Finvestkit_utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erishen%2Finvestkit_utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erishen","download_url":"https://codeload.github.com/erishen/investkit_utils/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erishen%2Finvestkit_utils/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34669839,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration","logging","python","shared-library","utilities"],"created_at":"2026-06-23T00:01:35.284Z","updated_at":"2026-06-23T00:01:36.756Z","avatar_url":"https://github.com/erishen.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# InvestKit Shared Module\n\n\u003e Unified configuration, logging, utilities, exceptions, type definitions, and testing tools for InvestKit projects.\n\n## Module Structure\n\n```\nsrc/investkit_utils/\n├── api_docs/             # API documentation aggregation\n├── cache/                # Cache management\n├── config/               # Configuration templates\n├── db/                   # Database utilities\n├── exceptions/           # Exception hierarchy\n│   ├── base.py           # Base exception\n│   └── handlers.py       # Exception handlers\n├── log_utils/            # Logging utilities\n│   ├── config.py         # Log configuration\n│   ├── context.py        # Context management\n│   ├── formatters.py     # Log formatters\n│   ├── logger.py         # Logger class\n│   └── manager.py        # Log manager\n├── testing/              # Test utilities\n│   ├── mocks.py          # Mock helpers\n│   ├── assertions.py     # Assertion utilities\n│   ├── fixtures.py       # Test fixtures\n│   └── data_generators.py# Test data generators\n├── types/                # Shared type definitions\n│   ├── enums.py          # Enumerations\n│   └── models.py         # Data models\n├── utils/                # General utilities\n│   ├── datetime_utils.py # Date/time helpers\n│   ├── retry.py          # Retry decorators\n│   ├── validators.py     # Data validators\n│   ├── numeric.py        # Numeric calculations\n│   └── string_utils.py   # String utilities\n└── __init__.py\n```\n\n## Quick Start\n\n```python\nfrom investkit_utils.log_utils import get_logger, setup_logging\nfrom investkit_utils.utils import retry\nfrom investkit_utils.exceptions import ValidationError\nfrom investkit_utils.types import StockInfo, TradeSignal, SignalType\n\n# Initialize logging\nsetup_logging(level=\"INFO\", log_format=\"json\")\n\n# Get logger\nlogger = get_logger(__name__)\nlogger.info_with_data(\"Operation completed\", {\"user_id\": \"123\"})\n\n# Retry decorator\n@retry(max_attempts=3, delay=1.0)\ndef fetch_data():\n    return requests.get(\"https://api.example.com/data\")\n\n# Type definitions\nsignal = TradeSignal(\n    symbol=\"000001\",\n    signal_type=SignalType.BUY,\n    confidence=0.85,\n    reason=\"MACD golden cross\"\n)\n```\n\n## 1. Unified Logging\n\n```python\nfrom investkit_utils.log_utils import get_logger, setup_logging\n\nsetup_logging(level=\"INFO\", log_format=\"json\", console=True)\nlogger = get_logger(__name__)\n\nlogger.info(\"Operation completed\")\nlogger.error(\"Operation failed\")\nlogger.info_with_data(\"User login\", {\"user_id\": \"123\", \"ip\": \"192.168.1.1\"})\n\n# Correlation ID for request tracing\nfrom investkit_utils.log_utils import set_correlation_id\nset_correlation_id(\"req-abc-123\")\n```\n\n**Log format:**\n\n```json\n{\n  \"timestamp\": \"2026-04-30T09:30:00.123456Z\",\n  \"level\": \"INFO\",\n  \"message\": \"User login successful\",\n  \"logger\": \"asset_lens.auth\",\n  \"correlation_id\": \"req-abc-123\",\n  \"data\": {\"user_id\": \"123\"}\n}\n```\n\n## 2. Configuration Template\n\n```bash\ncp shared/config/config.template.yaml your-project/config/settings.yaml\n```\n\n| Key | Description |\n|-----|-------------|\n| `app` | Application base config |\n| `logging` | Logging configuration |\n| `database` | Database configuration |\n| `cache` | Cache configuration |\n| `api` | API configuration |\n| `llm` | LLM configuration |\n| `data_sources` | Data source configuration |\n| `ml` | ML configuration |\n| `monitoring` | Monitoring configuration |\n| `security` | Security configuration |\n\n## 3. API Documentation Aggregation\n\n```bash\nmake api-docs\n# Visit http://localhost:8080\n```\n\n```python\nfrom investkit_utils.api_docs import serve_aggregated_docs\napp = serve_aggregated_docs(port=8080)\n```\n\n**Endpoints:**\n- http://localhost:8080 — Service list\n- http://localhost:8080/docs — Swagger UI\n- http://localhost:8080/redoc — ReDoc\n- http://localhost:8080/openapi.json — OpenAPI JSON\n\n## 4. Utility Functions\n\n```python\nfrom investkit_utils.utils import (\n    parse_date, format_date,\n    retry, retry_async,\n    validate_stock_code,\n    safe_divide, round_to, percentage_change,\n)\n\n# Date parsing\ndate_obj = parse_date(\"2026-04-30\")\ndate_str = format_date(date_obj)\n\n# Retry decorator\n@retry(max_attempts=3, delay=1.0)\ndef fetch_data(): ...\n\n@retry_async(max_attempts=3)\nasync def fetch_data_async(): ...\n\n# Data validation\nis_valid = validate_stock_code(\"000001\")\n\n# Numeric helpers\nresult = safe_divide(10, 0, default=0)      # → 0\nrounded = round_to(3.14159, 2)              # → 3.14\npct = percentage_change(100, 120)           # → 20.0\n```\n\n## 5. Unified Exception Handling\n\n```python\nfrom investkit_utils.exceptions import (\n    InvestKitError, ValidationError,\n    NotFoundError, AuthenticationError,\n    handle_exception,\n)\n\nraise ValidationError(\"Invalid stock code\", field=\"stock_code\", value=\"ABC\")\n\ntry:\n    ...\nexcept Exception as e:\n    error_dict = handle_exception(e)\n```\n\n| Exception | HTTP Status | Description |\n|-----------|------------|-------------|\n| `ValidationError` | 400 | Data validation error |\n| `AuthenticationError` | 401 | Authentication error |\n| `AuthorizationError` | 403 | Authorization error |\n| `NotFoundError` | 404 | Resource not found |\n| `RateLimitError` | 429 | Rate limit exceeded |\n| `DataError` | 422 | Data error |\n| `ExternalServiceError` | 502 | External service error |\n\n## 6. Shared Type Definitions\n\n```python\nfrom investkit_utils.types import (\n    SignalType, OrderType, OrderStatus, Market,\n    StockInfo, TradeSignal, Position, Portfolio,\n    Order, RiskMetrics, MLPrediction,\n)\n\nstock = StockInfo(code=\"000001\", name=\"Ping An Bank\", market=Market.SZ, industry=\"Banking\")\n\nsignal = TradeSignal(\n    symbol=\"000001\",\n    signal_type=SignalType.BUY,\n    confidence=0.85,\n    reason=\"MACD golden cross\"\n)\n\nportfolio = Portfolio(\n    name=\"My Portfolio\",\n    positions=[Position(symbol=\"000001\", quantity=100, cost_price=10.0)],\n    cash=10000.0\n)\nportfolio.calculate_totals()\n```\n\n## 7. Testing Utilities\n\n```python\nfrom investkit_utils.testing import (\n    mock_response, assert_dict_equal,\n    temp_directory, temp_file,\n    generate_test_stock_data, generate_test_portfolio,\n)\n\nresponse = mock_response({\"data\": \"test\"}, status_code=200)\nassert_dict_equal(actual, expected, ignore_keys=[\"timestamp\"])\n\nwith temp_directory() as tmpdir:\n    ...\n\nwith temp_file('{\"key\": \"value\"}', \".json\") as filepath:\n    ...\n\nstock_data = generate_test_stock_data(symbol=\"000001\", days=30)\nportfolio = generate_test_portfolio(symbols=[\"000001\", \"600000\"])\n```\n\n## Service Configuration\n\nDefault monitored services:\n\n| Service | URL | Prefix |\n|---------|-----|--------|\n| asset-lens | http://localhost:8000 | /api/asset |\n| langchain-llm-toolkit | http://localhost:8001 | /api/llm |\n| lobster | http://localhost:8002 | /api/lobster |\n\nCustom services:\n\n```python\nfrom investkit_utils.api_docs import APIService, aggregate_openapi_docs\n\nservices = [\n    APIService(\n        name=\"my-service\",\n        url=\"http://localhost:3000\",\n        description=\"My service\",\n        prefix=\"/api/my\",\n    )\n]\nspec = await aggregate_openapi_docs(services)\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferishen%2Finvestkit_utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferishen%2Finvestkit_utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferishen%2Finvestkit_utils/lists"}