mc-postgres-db 1.0.7__py3-none-any.whl → 1.0.9__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.
- mc_postgres_db-1.0.9.dist-info/METADATA +205 -0
- mc_postgres_db-1.0.9.dist-info/RECORD +5 -0
- mcpdb/tables.py +24 -11
- mc_postgres_db-1.0.7.dist-info/METADATA +0 -10
- mc_postgres_db-1.0.7.dist-info/RECORD +0 -5
- {mc_postgres_db-1.0.7.dist-info → mc_postgres_db-1.0.9.dist-info}/WHEEL +0 -0
- {mc_postgres_db-1.0.7.dist-info → mc_postgres_db-1.0.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: mc-postgres-db
|
3
|
+
Version: 1.0.9
|
4
|
+
Summary: Add your description here
|
5
|
+
Requires-Python: >=3.12
|
6
|
+
Description-Content-Type: text/markdown
|
7
|
+
Requires-Dist: alembic>=1.16.2
|
8
|
+
Requires-Dist: psycopg2-binary>=2.9.10
|
9
|
+
Requires-Dist: ruff>=0.12.0
|
10
|
+
Requires-Dist: sqlalchemy>=2.0.41
|
11
|
+
|
12
|
+
# MC Postgres DB
|
13
|
+
|
14
|
+
A Python package containing ORM models for a PostgreSQL database that powers a personal quantitative trading and investment analysis platform.
|
15
|
+
|
16
|
+
## Overview
|
17
|
+
|
18
|
+
This package provides SQLAlchemy ORM models and database utilities for managing financial data, trading strategies, portfolio analytics, and market research. The database serves as the backbone for a personal "quant hedge fund" project, storing everything from market data and content data.
|
19
|
+
|
20
|
+
## Features
|
21
|
+
|
22
|
+
- **Asset Models**: `AssetType` and `Asset` tables for categorizing and managing financial instruments and various fiat and digital currencies
|
23
|
+
- **Provider Models**: `ProviderType` and `Provider` tables for handling data sources and exchanges
|
24
|
+
- **Market Data Models**: `ProviderAssetMarket` table for storing OHLCV and bid/ask price data
|
25
|
+
- **Order Models**: `ProviderAssetOrder` table for tracking trading orders between assets
|
26
|
+
- **Content Models**: `ContentType`, `ProviderContent`, and `AssetContent` tables for managing news articles and social content
|
27
|
+
- **Relation Models**: `ProviderAsset` table for mapping relationships between providers and assets
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
### From PyPI
|
32
|
+
|
33
|
+
```bash
|
34
|
+
pip install mc-postgres-db
|
35
|
+
```
|
36
|
+
|
37
|
+
### From Source
|
38
|
+
|
39
|
+
```bash
|
40
|
+
# Clone the repository
|
41
|
+
git clone <repository-url>
|
42
|
+
cd mc-postgres-db
|
43
|
+
|
44
|
+
# Install using uv (recommended)
|
45
|
+
uv sync
|
46
|
+
```
|
47
|
+
|
48
|
+
## Database Setup
|
49
|
+
|
50
|
+
1. **PostgreSQL Setup**: Ensure PostgreSQL is installed and running
|
51
|
+
2. **Environment Variables**: Set up your database connection string
|
52
|
+
```bash
|
53
|
+
export SQLALCHEMY_DATABASE_URL="postgresql://username:password@localhost:5432/mc_trading_db"
|
54
|
+
```
|
55
|
+
|
56
|
+
## Usage
|
57
|
+
|
58
|
+
```python
|
59
|
+
from sqlalchemy import create_engine, select
|
60
|
+
from sqlalchemy.orm import Session
|
61
|
+
from mcpdb.tables import Asset, Provider, ProviderAssetMarket
|
62
|
+
|
63
|
+
# Create database connection
|
64
|
+
url = "postgresql://username:password@localhost:5432/mc_trading_db"
|
65
|
+
engine = create_engine(url)
|
66
|
+
|
67
|
+
# Query assets
|
68
|
+
with Session(engine) as session:
|
69
|
+
stmt = select(Asset).where(Asset.is_active)
|
70
|
+
assets = session.scalars(stmt).all()
|
71
|
+
asset_pairs = {asset.id: asset.name for asset in assets}
|
72
|
+
print("Available assets:")
|
73
|
+
for asset_id, asset_name in asset_pairs.items():
|
74
|
+
print(f"{asset_id}: {asset_name}")
|
75
|
+
|
76
|
+
# Query market data
|
77
|
+
with Session(engine) as session:
|
78
|
+
stmt = (
|
79
|
+
select(ProviderAssetMarket)
|
80
|
+
.where(
|
81
|
+
ProviderAssetMarket.asset_id == 1, # Bitcoin for example
|
82
|
+
ProviderAssetMarket.provider_id == 2, # Binance for example
|
83
|
+
)
|
84
|
+
.order_by(ProviderAssetMarket.timestamp.desc())
|
85
|
+
.limit(10)
|
86
|
+
)
|
87
|
+
market_data = session.scalars(stmt).all()
|
88
|
+
for data in market_data:
|
89
|
+
print(f"Timestamp: {data.timestamp}, Close: {data.close}, Volume: {data.volume}")
|
90
|
+
|
91
|
+
# Get assets from a provider
|
92
|
+
with Session(engine) as session:
|
93
|
+
stmt = select(Provider).where(Provider.id == 1)
|
94
|
+
provider = session.scalars(stmt).one()
|
95
|
+
provider_assets = provider.get_all_assets(engine)
|
96
|
+
print(f"Assets available from {provider.name}:")
|
97
|
+
for provider_asset in provider_assets:
|
98
|
+
print(f"Asset code: {provider_asset.asset_code}")
|
99
|
+
```
|
100
|
+
|
101
|
+
## Models Overview
|
102
|
+
|
103
|
+
### Core Models
|
104
|
+
|
105
|
+
- **AssetType**: Categorizes assets (e.g., stocks, bonds, cryptocurrencies) with names and descriptions
|
106
|
+
- **Asset**: Represents financial instruments with references to asset types, symbols, and optional underlying assets
|
107
|
+
- **ProviderType**: Categorizes data providers (e.g., exchanges, news services) with names and descriptions
|
108
|
+
- **Provider**: Represents data sources with references to provider types and optional underlying providers
|
109
|
+
- **ProviderAsset**: Maps the relationship between providers and assets with asset codes and active status
|
110
|
+
- **ProviderAssetOrder**: Tracks orders for assets from providers including timestamp, price, and volume
|
111
|
+
- **ProviderAssetMarket**: Stores OHLCV (Open, High, Low, Close, Volume) market data and bid/ask prices
|
112
|
+
- **ContentType**: Categorizes content (e.g., news articles, social media posts) with names and descriptions
|
113
|
+
- **ProviderContent**: Stores content from providers with timestamps, titles, descriptions, and full content
|
114
|
+
- **AssetContent**: Maps the relationship between content and assets
|
115
|
+
|
116
|
+
### Database Schema Features
|
117
|
+
|
118
|
+
- **Inheritance Support**: Assets and providers can reference underlying entities for hierarchical relationships
|
119
|
+
- **Timestamped Records**: All tables include creation and update timestamps
|
120
|
+
- **Soft Delete Pattern**: Uses is_active flags to mark records as inactive without deletion
|
121
|
+
- **Time Series Data**: Market data is organized by timestamp for efficient time-series operations
|
122
|
+
- **Cross-Reference Tables**: Enables many-to-many relationships between assets, providers, and content
|
123
|
+
|
124
|
+
## Development
|
125
|
+
|
126
|
+
### Setting up Development Environment
|
127
|
+
|
128
|
+
```bash
|
129
|
+
# Install development dependencies using uv
|
130
|
+
uv sync --dev
|
131
|
+
|
132
|
+
# Run tests
|
133
|
+
uv run pytest
|
134
|
+
|
135
|
+
# Run linting
|
136
|
+
uv run ruff check src/mcpdb/
|
137
|
+
uv run ruff format src/mcpdb/
|
138
|
+
```
|
139
|
+
|
140
|
+
### Database Migrations
|
141
|
+
|
142
|
+
```bash
|
143
|
+
# Generate new migration
|
144
|
+
uv run alembic revision --autogenerate -m "Description of changes"
|
145
|
+
|
146
|
+
# Apply migrations
|
147
|
+
uv run alembic upgrade head
|
148
|
+
|
149
|
+
# Rollback migration
|
150
|
+
uv run alembic downgrade -1
|
151
|
+
```
|
152
|
+
|
153
|
+
## Project Structure
|
154
|
+
|
155
|
+
```
|
156
|
+
mc-postgres-db/
|
157
|
+
├── src/ # Source code directory
|
158
|
+
│ └── mcpdb/ # Package directory
|
159
|
+
│ └── tables.py # SQLAlchemy ORM models
|
160
|
+
├── tests/ # Unit and integration tests
|
161
|
+
├── scripts/ # Database maintenance scripts
|
162
|
+
├── pyproject.toml # Project configuration and dependencies
|
163
|
+
├── uv.lock # Locked dependency versions
|
164
|
+
└── README.md # Project documentation
|
165
|
+
```
|
166
|
+
|
167
|
+
## Data Sources
|
168
|
+
|
169
|
+
This database integrates with various financial data providers:
|
170
|
+
|
171
|
+
- Market data APIs (Alpha Vantage, IEX Cloud, etc.)
|
172
|
+
- Fundamental data providers
|
173
|
+
- Alternative data sources
|
174
|
+
- Custom scraped data
|
175
|
+
|
176
|
+
## Security & Compliance
|
177
|
+
|
178
|
+
- Database connections use SSL encryption
|
179
|
+
- Sensitive data is encrypted at rest
|
180
|
+
- Access controls and audit logging implemented
|
181
|
+
- Regular backups and disaster recovery procedures
|
182
|
+
|
183
|
+
## Performance Considerations
|
184
|
+
|
185
|
+
- Optimized indexes for common query patterns
|
186
|
+
- Partitioned tables for large time-series data
|
187
|
+
- Connection pooling for high-throughput operations
|
188
|
+
- Caching layer for frequently accessed data
|
189
|
+
|
190
|
+
## Contributing
|
191
|
+
|
192
|
+
This is a personal project, but suggestions and improvements are welcome:
|
193
|
+
|
194
|
+
1. Fork the repository
|
195
|
+
2. Create a feature branch
|
196
|
+
3. Make your changes with tests
|
197
|
+
4. Submit a pull request
|
198
|
+
|
199
|
+
## License
|
200
|
+
|
201
|
+
This project is for personal use and learning purposes.
|
202
|
+
|
203
|
+
## Disclaimer
|
204
|
+
|
205
|
+
This software is for educational and personal use only. It is not intended for production trading or investment advice. Use at your own risk.
|
@@ -0,0 +1,5 @@
|
|
1
|
+
mcpdb/tables.py,sha256=6RWuE8eJzShSWG_wg_qgjwZ5UuhLu81JZiuTvRomOiM,11008
|
2
|
+
mc_postgres_db-1.0.9.dist-info/METADATA,sha256=vYbruza1zMgKJQsb_uwaFYAqJMh_HgqGUKXThhrMpxY,7052
|
3
|
+
mc_postgres_db-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
4
|
+
mc_postgres_db-1.0.9.dist-info/top_level.txt,sha256=xiCw1E_-H0o0I8j5PbuWddHW1iwrGwntb2enCqa4FQA,6
|
5
|
+
mc_postgres_db-1.0.9.dist-info/RECORD,,
|
mcpdb/tables.py
CHANGED
@@ -20,8 +20,8 @@ class AssetType(Base):
|
|
20
20
|
__tablename__ = "asset_type"
|
21
21
|
|
22
22
|
id: Mapped[int] = mapped_column(primary_key=True)
|
23
|
-
name: Mapped[str] = mapped_column(String(
|
24
|
-
description: Mapped[Optional[str]] = mapped_column(String(
|
23
|
+
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
24
|
+
description: Mapped[Optional[str]] = mapped_column(String(1000), nullable=True)
|
25
25
|
is_active: Mapped[bool] = mapped_column(default=True)
|
26
26
|
created_at: Mapped[datetime.datetime] = mapped_column(
|
27
27
|
nullable=False, server_default=func.now()
|
@@ -41,8 +41,12 @@ class Asset(Base):
|
|
41
41
|
asset_type_id: Mapped[int] = mapped_column(
|
42
42
|
ForeignKey("asset_type.id"), nullable=False
|
43
43
|
)
|
44
|
-
name: Mapped[str] = mapped_column(String(
|
44
|
+
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
45
45
|
description: Mapped[Optional[str]]
|
46
|
+
symbol: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
47
|
+
underlying_asset_id: Mapped[Optional[int]] = mapped_column(
|
48
|
+
ForeignKey("asset.id"), nullable=True
|
49
|
+
)
|
46
50
|
is_active: Mapped[bool] = mapped_column(default=True)
|
47
51
|
created_at: Mapped[datetime.datetime] = mapped_column(
|
48
52
|
nullable=False, server_default=func.now()
|
@@ -59,7 +63,7 @@ class ProviderType(Base):
|
|
59
63
|
__tablename__ = "provider_type"
|
60
64
|
|
61
65
|
id: Mapped[int] = mapped_column(primary_key=True)
|
62
|
-
name: Mapped[str] = mapped_column(String(
|
66
|
+
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
63
67
|
description: Mapped[Optional[str]] = mapped_column(String(1000), nullable=True)
|
64
68
|
is_active: Mapped[bool] = mapped_column(default=True)
|
65
69
|
created_at: Mapped[datetime.datetime] = mapped_column(
|
@@ -80,8 +84,12 @@ class Provider(Base):
|
|
80
84
|
provider_type_id: Mapped[int] = mapped_column(
|
81
85
|
ForeignKey("provider_type.id"), nullable=False
|
82
86
|
)
|
83
|
-
name: Mapped[str] = mapped_column(String(
|
87
|
+
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
84
88
|
description: Mapped[Optional[str]] = mapped_column(String(1000), nullable=True)
|
89
|
+
symbol: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
90
|
+
underlying_provider_id: Mapped[Optional[int]] = mapped_column(
|
91
|
+
ForeignKey("provider.id"), nullable=True
|
92
|
+
)
|
85
93
|
is_active: Mapped[bool] = mapped_column(default=True)
|
86
94
|
created_at: Mapped[datetime.datetime] = mapped_column(
|
87
95
|
nullable=False, server_default=func.now()
|
@@ -147,7 +155,7 @@ class ProviderAsset(Base):
|
|
147
155
|
asset_id: Mapped[int] = mapped_column(
|
148
156
|
ForeignKey("asset.id"), nullable=False, primary_key=True
|
149
157
|
)
|
150
|
-
asset_code: Mapped[str] = mapped_column(String(
|
158
|
+
asset_code: Mapped[str] = mapped_column(String(100), nullable=False)
|
151
159
|
is_active: Mapped[bool] = mapped_column(default=True)
|
152
160
|
created_at: Mapped[datetime.datetime] = mapped_column(
|
153
161
|
nullable=False, server_default=func.now()
|
@@ -203,7 +211,7 @@ class ContentType(Base):
|
|
203
211
|
__tablename__ = "content_type"
|
204
212
|
|
205
213
|
id: Mapped[int] = mapped_column(primary_key=True)
|
206
|
-
name: Mapped[str] = mapped_column(String(
|
214
|
+
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
207
215
|
description: Mapped[Optional[str]] = mapped_column(String(1000), nullable=True)
|
208
216
|
is_active: Mapped[bool] = mapped_column(default=True)
|
209
217
|
created_at: Mapped[datetime.datetime] = mapped_column(
|
@@ -223,14 +231,19 @@ class ProviderContent(Base):
|
|
223
231
|
id: Mapped[int] = mapped_column(primary_key=True)
|
224
232
|
timestamp: Mapped[datetime.datetime] = mapped_column(nullable=False)
|
225
233
|
provider_id: Mapped[int] = mapped_column(ForeignKey("provider.id"), nullable=False)
|
226
|
-
|
227
|
-
String(1000),
|
234
|
+
provider_external_code: Mapped[str] = mapped_column(
|
235
|
+
String(1000),
|
236
|
+
nullable=False,
|
237
|
+
comment="This is the external identifier for the content and will depend on the content provider and the type of content. For example, for a news article, it could be the URL of the article and for a social media post, it could be the post ID.",
|
228
238
|
)
|
229
239
|
content_type_id: Mapped[int] = mapped_column(
|
230
240
|
ForeignKey("content_type.id"), nullable=False
|
231
241
|
)
|
232
|
-
|
233
|
-
title: Mapped[Optional[str]] = mapped_column(String(
|
242
|
+
authors: Mapped[Optional[str]] = mapped_column(String(1000), nullable=True)
|
243
|
+
title: Mapped[Optional[str]] = mapped_column(String(1000), nullable=True)
|
244
|
+
description: Mapped[Optional[str]] = mapped_column(
|
245
|
+
String(5000), nullable=True, comment="A short description of the content"
|
246
|
+
)
|
234
247
|
content: Mapped[str] = mapped_column(String(), nullable=False)
|
235
248
|
created_at: Mapped[datetime.datetime] = mapped_column(
|
236
249
|
nullable=False, server_default=func.now()
|
@@ -1,10 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: mc-postgres-db
|
3
|
-
Version: 1.0.7
|
4
|
-
Summary: Add your description here
|
5
|
-
Requires-Python: >=3.12
|
6
|
-
Description-Content-Type: text/markdown
|
7
|
-
Requires-Dist: alembic>=1.16.2
|
8
|
-
Requires-Dist: psycopg2-binary>=2.9.10
|
9
|
-
Requires-Dist: ruff>=0.12.0
|
10
|
-
Requires-Dist: sqlalchemy>=2.0.41
|
@@ -1,5 +0,0 @@
|
|
1
|
-
mcpdb/tables.py,sha256=jeyQH3u7DvOxLpIM6u5AaSLrBaL5UxvXTFK29ytJ_A8,10201
|
2
|
-
mc_postgres_db-1.0.7.dist-info/METADATA,sha256=Lwnx5ZHsUvxPpJRGVqH8JQBijeEtQFUHPmEwCj3bIfE,289
|
3
|
-
mc_postgres_db-1.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
4
|
-
mc_postgres_db-1.0.7.dist-info/top_level.txt,sha256=xiCw1E_-H0o0I8j5PbuWddHW1iwrGwntb2enCqa4FQA,6
|
5
|
-
mc_postgres_db-1.0.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|