First commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.env
|
||||
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"python-envs.defaultEnvManager": "ms-python.python:conda",
|
||||
"python-envs.defaultPackageManager": "ms-python.python:conda"
|
||||
}
|
||||
BIN
modules/__pycache__/api.cpython-313.pyc
Normal file
BIN
modules/__pycache__/api.cpython-313.pyc
Normal file
Binary file not shown.
42
modules/api.py
Normal file
42
modules/api.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import requests
|
||||
from py_clob_client.client import ClobClient
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
### Functions ###
|
||||
def check_geoblock() -> None:
|
||||
response = requests.get("https://polymarket.com/api/geoblock")
|
||||
geo = response.json()
|
||||
if geo["blocked"]:
|
||||
print(f"Trading not available in {geo['country']}")
|
||||
raise ValueError('GEOBLOCKED - KILLING SCRIPT')
|
||||
else:
|
||||
print("Trading available")
|
||||
|
||||
def create_client():
|
||||
print('creating client...')
|
||||
load_dotenv()
|
||||
private_key = os.getenv("PRIVATE_KEY")
|
||||
host = "https://clob.polymarket.com"
|
||||
chain_id = 137 # Polygon mainnet
|
||||
|
||||
temp_client = ClobClient(host, key=private_key, chain_id=chain_id)
|
||||
api_creds = temp_client.create_or_derive_api_creds()
|
||||
|
||||
client = ClobClient(
|
||||
host,
|
||||
key=private_key,
|
||||
chain_id=chain_id,
|
||||
creds=api_creds,
|
||||
signature_type=2, # Rabby
|
||||
funder=os.getenv("FUNDER")
|
||||
# funder="0xb2967A7e578E700E27611238B7F762BdADC72CcB"
|
||||
# 0x2bb5be619b8f348954dd2290abcd267735a9f4a0
|
||||
|
||||
)
|
||||
# View your trade history
|
||||
trades = client.get_trades()
|
||||
print(f"You've made {len(trades)} trades")
|
||||
print('client created successfully!')
|
||||
|
||||
return client
|
||||
681
order_entry.ipynb
Normal file
681
order_entry.ipynb
Normal file
@@ -0,0 +1,681 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 64,
|
||||
"id": "c0bfb3b5",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import modules.api as api\n",
|
||||
"import pandas as pd\n",
|
||||
"from datetime import datetime, timezone, timedelta\n",
|
||||
"import math\n",
|
||||
"import requests\n",
|
||||
"import json\n",
|
||||
"from dataclasses import dataclass\n",
|
||||
"\n",
|
||||
"from py_clob_client.clob_types import OrderArgs, OrderType, PostOrdersArgs, PartialCreateOrderOptions\n",
|
||||
"from py_clob_client.order_builder.constants import BUY, SELL\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 65,
|
||||
"id": "7d7dc787",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def time_round_down(dt, interval_mins=5) -> int: # returns timestamp in seconds\n",
|
||||
" interval_secs = interval_mins * 60\n",
|
||||
" seconds = dt.timestamp()\n",
|
||||
" rounded_seconds = math.floor(seconds / interval_secs) * interval_secs\n",
|
||||
" \n",
|
||||
" return rounded_seconds\n",
|
||||
"\n",
|
||||
"def get_mkt_details_by_slug(slug: str) -> dict[str, str, str]: # {'Up' : 123, 'Down': 456, 'isActive': True, 'MinTickSize': 0.01, 'isNegRisk': False}\n",
|
||||
" r = requests.get(f\"https://gamma-api.polymarket.com/events/slug/{slug}\")\n",
|
||||
" market = r.json()['markets'][0]\n",
|
||||
" token_ids = json.loads(market.get(\"clobTokenIds\", \"[]\"))\n",
|
||||
" outcomes = json.loads(market.get(\"outcomes\", \"[]\"))\n",
|
||||
" d = dict(zip(outcomes, token_ids))\n",
|
||||
" d['isActive'] = market['negRisk']\n",
|
||||
" d['MinTickSize'] = market['orderPriceMinTickSize']\n",
|
||||
" d['isNegRisk'] = market['negRisk']\n",
|
||||
" d['ConditionId'] = market['conditionId']\n",
|
||||
"\n",
|
||||
" return d, market"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 66,
|
||||
"id": "c3e07e21",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Timestamp('2026-03-27 03:15:00')"
|
||||
]
|
||||
},
|
||||
"execution_count": 66,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"slug_prefix = 'btc-updown-5m-'\n",
|
||||
"slug_time_id = time_round_down(dt=datetime.now(timezone.utc))\n",
|
||||
"slug_full = slug_prefix + str(slug_time_id)\n",
|
||||
"market_details, market = get_mkt_details_by_slug(slug_full)\n",
|
||||
"pd.to_datetime(slug_time_id, unit='s')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 67,
|
||||
"id": "5ba43ffc",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'Up': '97875487643168796351669326324566509161830383659944117871160601839654217457417',\n",
|
||||
" 'Down': '96344823573113580705457152659674776966355813491715728702490170635510049560213',\n",
|
||||
" 'isActive': False,\n",
|
||||
" 'MinTickSize': 0.01,\n",
|
||||
" 'isNegRisk': False,\n",
|
||||
" 'ConditionId': '0x071d8568d3d736502bd450e150ef93481992d1d26df0c094cc119246d8931a23'}"
|
||||
]
|
||||
},
|
||||
"execution_count": 67,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"market_details"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 61,
|
||||
"id": "5d356d3b",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"creating client...\n",
|
||||
"You've made 41 trades\n",
|
||||
"client created successfully!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"client = api.create_client()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 62,
|
||||
"id": "bebb53eb",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{'price': '0.84', 'side': 'BUY'}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"last = client.get_last_trade_price(market_details['Up'])\n",
|
||||
"print(last)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "bae5e6a9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 63,
|
||||
"id": "52c0c38a",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[{'errorMsg': '', 'orderID': '0x4e8e8b193d91c2d4e7b455d3d654a26697ee3289399a9140b2b1888dda7b9a16', 'takingAmount': '10', 'makingAmount': '1.7', 'status': 'matched', 'transactionsHashes': ['0x4f66978cc001a819d9ba266f708148f0512414627a59ffd9a48d8e4b92e5a716'], 'success': True}, {'errorMsg': '', 'orderID': '0x6c5aad6b231c8a6d7a91c1260fe31955e3715e6557aaa773029bd9ec42f26917', 'takingAmount': '', 'makingAmount': '', 'status': 'live', 'success': True}]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"response = client.post_orders([\n",
|
||||
" PostOrdersArgs(\n",
|
||||
" order=client.create_order(\n",
|
||||
" order_args=OrderArgs(\n",
|
||||
" token_id=market_details['Up'],\n",
|
||||
" price=0.90,\n",
|
||||
" size=10,\n",
|
||||
" side=BUY,\n",
|
||||
" ),\n",
|
||||
" options=PartialCreateOrderOptions(\n",
|
||||
" tick_size=str(market_details['MinTickSize']),\n",
|
||||
" neg_risk=market_details['isNegRisk']\n",
|
||||
" ),\n",
|
||||
" ),\n",
|
||||
" orderType=OrderType.GTC,\n",
|
||||
" postOnly=False,\n",
|
||||
" ),\n",
|
||||
" PostOrdersArgs(\n",
|
||||
" order=client.create_order(\n",
|
||||
" order_args=OrderArgs(\n",
|
||||
" token_id=market_details['Down'],\n",
|
||||
" price=0.10,\n",
|
||||
" size=10,\n",
|
||||
" side=BUY,\n",
|
||||
" ),\n",
|
||||
" options=PartialCreateOrderOptions(\n",
|
||||
" tick_size=str(market_details['MinTickSize']),\n",
|
||||
" neg_risk=market_details['isNegRisk']\n",
|
||||
" ),\n",
|
||||
" ),\n",
|
||||
" orderType=OrderType.GTC,\n",
|
||||
" postOnly=True,\n",
|
||||
" ),\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"print(response)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "52a7229b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "fb5f066a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "4b3ccf83",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 68,
|
||||
"id": "75d45cd8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"d = [{'asset_id': '97987758532314346863331680319607711694838937984814950023901315671390566048932', 'price': '0.37', 'size': '429.41', 'side': 'BUY', 'hash': '999d5b73d83a840c0df7dc2d817ae55a242845d5', 'best_bid': '0.37', 'best_ask': '0.38'}, {'asset_id': '92959981857766705879127008770062050214089835506649207585188324269480756219695', 'price': '0.63', 'size': '429.41', 'side': 'SELL', 'hash': 'ead5af5a55f8b125b1e50f1c80a783c3c2d33187', 'best_bid': '0.62', 'best_ask': '0.63'}]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 69,
|
||||
"id": "f608378f",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.microsoft.datawrangler.viewer.v0+json": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "index",
|
||||
"rawType": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"name": "asset_id",
|
||||
"rawType": "object",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "price",
|
||||
"rawType": "object",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "size",
|
||||
"rawType": "object",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "side",
|
||||
"rawType": "object",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "hash",
|
||||
"rawType": "object",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "best_bid",
|
||||
"rawType": "object",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "best_ask",
|
||||
"rawType": "object",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"ref": "310c4763-20db-4051-931a-ef52e1b6513b",
|
||||
"rows": [
|
||||
[
|
||||
"0",
|
||||
"97987758532314346863331680319607711694838937984814950023901315671390566048932",
|
||||
"0.37",
|
||||
"429.41",
|
||||
"BUY",
|
||||
"999d5b73d83a840c0df7dc2d817ae55a242845d5",
|
||||
"0.37",
|
||||
"0.38"
|
||||
],
|
||||
[
|
||||
"1",
|
||||
"92959981857766705879127008770062050214089835506649207585188324269480756219695",
|
||||
"0.63",
|
||||
"429.41",
|
||||
"SELL",
|
||||
"ead5af5a55f8b125b1e50f1c80a783c3c2d33187",
|
||||
"0.62",
|
||||
"0.63"
|
||||
]
|
||||
],
|
||||
"shape": {
|
||||
"columns": 7,
|
||||
"rows": 2
|
||||
}
|
||||
},
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style scoped>\n",
|
||||
" .dataframe tbody tr th:only-of-type {\n",
|
||||
" vertical-align: middle;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>asset_id</th>\n",
|
||||
" <th>price</th>\n",
|
||||
" <th>size</th>\n",
|
||||
" <th>side</th>\n",
|
||||
" <th>hash</th>\n",
|
||||
" <th>best_bid</th>\n",
|
||||
" <th>best_ask</th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>9798775853231434686333168031960771169483893798...</td>\n",
|
||||
" <td>0.37</td>\n",
|
||||
" <td>429.41</td>\n",
|
||||
" <td>BUY</td>\n",
|
||||
" <td>999d5b73d83a840c0df7dc2d817ae55a242845d5</td>\n",
|
||||
" <td>0.37</td>\n",
|
||||
" <td>0.38</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>9295998185776670587912700877006205021408983550...</td>\n",
|
||||
" <td>0.63</td>\n",
|
||||
" <td>429.41</td>\n",
|
||||
" <td>SELL</td>\n",
|
||||
" <td>ead5af5a55f8b125b1e50f1c80a783c3c2d33187</td>\n",
|
||||
" <td>0.62</td>\n",
|
||||
" <td>0.63</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" asset_id price size side \\\n",
|
||||
"0 9798775853231434686333168031960771169483893798... 0.37 429.41 BUY \n",
|
||||
"1 9295998185776670587912700877006205021408983550... 0.63 429.41 SELL \n",
|
||||
"\n",
|
||||
" hash best_bid best_ask \n",
|
||||
"0 999d5b73d83a840c0df7dc2d817ae55a242845d5 0.37 0.38 \n",
|
||||
"1 ead5af5a55f8b125b1e50f1c80a783c3c2d33187 0.62 0.63 "
|
||||
]
|
||||
},
|
||||
"execution_count": 69,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"pd.DataFrame(d)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "2fe32a82",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "7603be6c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 75,
|
||||
"id": "c099da9a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"start = 1774585800\n",
|
||||
"end = 1774585800 + 60*5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b631306d",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Timestamp('2026-03-27 04:35:00')"
|
||||
]
|
||||
},
|
||||
"execution_count": 76,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"pd.to_datetime(start, unit='s')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 77,
|
||||
"id": "685d7dd9",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"300"
|
||||
]
|
||||
},
|
||||
"execution_count": 77,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"end - start"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 78,
|
||||
"id": "bdd681cc",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def format_timestamp(total_seconds):\n",
|
||||
" minutes, seconds = divmod(total_seconds, 60)\n",
|
||||
" print(f\"{minutes} minutes and {seconds} seconds\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 79,
|
||||
"id": "7ba83cea",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"5 minutes and 0 seconds\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"format_timestamp(end - start)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 88,
|
||||
"id": "4e211e0d",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"1774586619"
|
||||
]
|
||||
},
|
||||
"execution_count": 88,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"round(datetime.now().timestamp())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "5dabe016",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"1774585800"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 111,
|
||||
"id": "8a65ba6f",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Timestamp('2026-03-27 03:20:00')"
|
||||
]
|
||||
},
|
||||
"execution_count": 111,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"pd.to_datetime(1774581600, unit='s')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 91,
|
||||
"id": "83f63c10",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sdt = '2026-03-27T03:20:00Z'"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 110,
|
||||
"id": "1f907a71",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"1774581600"
|
||||
]
|
||||
},
|
||||
"execution_count": 110,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"round(datetime.strptime(sdt, '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc).timestamp())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 113,
|
||||
"id": "fe7c0c12",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"d = {\"connection_id\":\"a4-i0ecArPECFLQ=\",\"payload\":{\"full_accuracy_value\":\"65779051825748830000000\",\"symbol\":\"btc/usd\",\"timestamp\":1774627572000,\"value\":65779.05182574883},\"timestamp\":1774627573524,\"topic\":\"crypto_prices_chainlink\",\"type\":\"update\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 114,
|
||||
"id": "a98ace05",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'connection_id': 'a4-i0ecArPECFLQ=',\n",
|
||||
" 'payload': {'full_accuracy_value': '65779051825748830000000',\n",
|
||||
" 'symbol': 'btc/usd',\n",
|
||||
" 'timestamp': 1774627572000,\n",
|
||||
" 'value': 65779.05182574883},\n",
|
||||
" 'timestamp': 1774627573524,\n",
|
||||
" 'topic': 'crypto_prices_chainlink',\n",
|
||||
" 'type': 'update'}"
|
||||
]
|
||||
},
|
||||
"execution_count": 114,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 120,
|
||||
"id": "d2278853",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Timestamp('2026-03-27 16:06:13.524000')"
|
||||
]
|
||||
},
|
||||
"execution_count": 120,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"pd.to_datetime(d['timestamp'], unit='ms')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "008cb5c9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f6c647b7",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e1b8d116",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "3f1e3a83",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "py313",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.13.2"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
150
ws.py
Normal file
150
ws.py
Normal file
@@ -0,0 +1,150 @@
|
||||
import asyncio
|
||||
import json
|
||||
import math
|
||||
import pandas as pd
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
import websockets
|
||||
import numpy as np
|
||||
import talib
|
||||
import requests
|
||||
|
||||
WSS_URL = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
|
||||
SLUG_END_TIME = 0
|
||||
|
||||
HIST_TRADES = np.empty((0, 2))
|
||||
|
||||
def format_timestamp(total_seconds) -> str:
|
||||
minutes, seconds = divmod(total_seconds, 60)
|
||||
return f"{minutes} minutes and {seconds} seconds"
|
||||
|
||||
def time_round_down(dt, interval_mins=5) -> int: # returns timestamp in seconds
|
||||
interval_secs = interval_mins * 60
|
||||
seconds = dt.timestamp()
|
||||
rounded_seconds = math.floor(seconds / interval_secs) * interval_secs
|
||||
|
||||
return rounded_seconds
|
||||
|
||||
def get_mkt_details_by_slug(slug: str) -> dict[str, str, str]: # {'Up' : 123, 'Down': 456, 'isActive': True, 'MinTickSize': 0.01, 'isNegRisk': False}
|
||||
r = requests.get(f"https://gamma-api.polymarket.com/events/slug/{slug}")
|
||||
market = r.json()['markets'][0]
|
||||
token_ids = json.loads(market.get("clobTokenIds", "[]"))
|
||||
outcomes = json.loads(market.get("outcomes", "[]"))
|
||||
d = dict(zip(outcomes, token_ids))
|
||||
d['isActive'] = market['negRisk']
|
||||
d['MinTickSize'] = market['orderPriceMinTickSize']
|
||||
d['isNegRisk'] = market['negRisk']
|
||||
d['ConditionId'] = market['conditionId']
|
||||
d['EndDateTime'] = market['endDate']
|
||||
|
||||
return d, market
|
||||
|
||||
def gen_slug():
|
||||
slug_prefix = 'btc-updown-5m-'
|
||||
slug_time_id = time_round_down(dt=datetime.now(timezone.utc))
|
||||
return slug_prefix + str(slug_time_id)
|
||||
|
||||
|
||||
async def polymarket_stream():
|
||||
global SLUG_END_TIME
|
||||
global HIST_TRADES
|
||||
|
||||
slug_full = gen_slug()
|
||||
market_details, market = get_mkt_details_by_slug(slug_full)
|
||||
TARGET_ASSET_ID = market_details['Up']
|
||||
SLUG_END_TIME = round(datetime.strptime(market_details['EndDateTime'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc).timestamp())
|
||||
print(f'********* NEW MKT - END DATETIME: {pd.to_datetime(SLUG_END_TIME, unit='s')} *********')
|
||||
|
||||
async with websockets.connect(WSS_URL) as websocket:
|
||||
print(f"Connected to {WSS_URL}")
|
||||
|
||||
subscribe_msg = {
|
||||
"assets_ids": [TARGET_ASSET_ID],
|
||||
"type": "market",
|
||||
"custom_feature_enabled": True
|
||||
}
|
||||
|
||||
await websocket.send(json.dumps(subscribe_msg))
|
||||
print(f"Subscribed to Asset: {TARGET_ASSET_ID}")
|
||||
|
||||
try:
|
||||
async for message in websocket:
|
||||
current_ts = round(datetime.now().timestamp())
|
||||
sec_remaining = SLUG_END_TIME - current_ts
|
||||
|
||||
if sec_remaining <= 0:
|
||||
HIST_TRADES = np.empty((0, 2))
|
||||
|
||||
print('*** Attempting to unsub from past 5min')
|
||||
update_unsub_msg = {
|
||||
"operation": 'unsubscribe',
|
||||
"assets_ids": [TARGET_ASSET_ID],
|
||||
"custom_feature_enabled": True
|
||||
}
|
||||
await websocket.send(json.dumps(update_unsub_msg))
|
||||
|
||||
print('*** Attempting to SUB to new 5min')
|
||||
slug_full = gen_slug()
|
||||
market_details, market = get_mkt_details_by_slug(slug_full)
|
||||
TARGET_ASSET_ID = market_details['Up']
|
||||
SLUG_END_TIME = round(datetime.strptime(market_details['EndDateTime'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc).timestamp())
|
||||
|
||||
update_sub_msg = {
|
||||
"operation": 'subscribe',
|
||||
"assets_ids": [TARGET_ASSET_ID],
|
||||
"custom_feature_enabled": True
|
||||
}
|
||||
await websocket.send(json.dumps(update_sub_msg))
|
||||
|
||||
|
||||
if isinstance(message, str):
|
||||
data = json.loads(message)
|
||||
|
||||
if isinstance(data, dict):
|
||||
# print(data.get("event_type", None))
|
||||
pass
|
||||
elif isinstance(data, list):
|
||||
print('initial book: ')
|
||||
print(data)
|
||||
continue
|
||||
else:
|
||||
raise ValueError(f'Type: {type(data)} not expected: {message}')
|
||||
|
||||
event_type = data.get("event_type", None)
|
||||
|
||||
if event_type == "price_change":
|
||||
# print("📈 Price Change")
|
||||
# print(pd.DataFrame(data['price_changes']))
|
||||
pass
|
||||
elif event_type == "best_bid_ask":
|
||||
# print(pd.DataFrame([data]))
|
||||
pass
|
||||
elif event_type == "last_trade_price":
|
||||
px = float(data['price'])
|
||||
qty = float(data['size'])
|
||||
HIST_TRADES = np.append(HIST_TRADES, np.array([[px, qty]]), axis=0)
|
||||
SMA = talib.ROC(HIST_TRADES[:,0], timeperiod=10)[-1]
|
||||
print(f"✨ Last Px: {px:.2f}; ROC: {SMA:.4f}; Qty: {qty:6.2f}; Sec Left: {sec_remaining}")
|
||||
elif event_type == "book":
|
||||
pass
|
||||
elif event_type == "new_market":
|
||||
print('Received new_market')
|
||||
elif event_type == "market_resolved":
|
||||
print(f"Received: {event_type}")
|
||||
print(data)
|
||||
elif event_type == "tick_size_change": # may want for CLOB order routing
|
||||
print(f"Received: {event_type}")
|
||||
print(data)
|
||||
else:
|
||||
print(f"Received: {event_type}")
|
||||
print(data)
|
||||
|
||||
except websockets.ConnectionClosed:
|
||||
print("Connection closed by server.")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
asyncio.run(polymarket_stream())
|
||||
except KeyboardInterrupt:
|
||||
print("Stream stopped.")
|
||||
61
ws_rtds.py
Normal file
61
ws_rtds.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import asyncio
|
||||
import json
|
||||
import math
|
||||
import pandas as pd
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
import websockets
|
||||
import numpy as np
|
||||
import talib
|
||||
import requests
|
||||
|
||||
WSS_URL = "wss://ws-live-data.polymarket.com"
|
||||
|
||||
HIST_TRADES = np.empty((0, 2))
|
||||
|
||||
|
||||
async def rtds_stream():
|
||||
global HIST_TRADES
|
||||
|
||||
async with websockets.connect(WSS_URL) as websocket:
|
||||
print(f"Connected to {WSS_URL}")
|
||||
|
||||
subscribe_msg = {
|
||||
"action": "subscribe",
|
||||
"subscriptions": [
|
||||
{
|
||||
"topic": "crypto_prices_chainlink",
|
||||
"type": "*",
|
||||
"filters": "{\"symbol\":\"btc/usd\"}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
await websocket.send(json.dumps(subscribe_msg))
|
||||
|
||||
try:
|
||||
async for message in websocket:
|
||||
if isinstance(message, str):
|
||||
try:
|
||||
data = json.loads(message)
|
||||
if data['payload'].get('value', None) is not None:
|
||||
print(f'🤑 BTC Chainlink Last Px: {data['payload']['value']:_.4f}; TS: {pd.to_datetime(data['timestamp'], unit='ms')}')
|
||||
else:
|
||||
print(f'Initial or unexpected data struct, skipping: {data}')
|
||||
continue
|
||||
except (json.JSONDecodeError, ValueError):
|
||||
print(f'Message not in JSON format, skipping: {message}')
|
||||
continue
|
||||
else:
|
||||
raise ValueError(f'Type: {type(data)} not expected: {message}')
|
||||
|
||||
|
||||
except websockets.ConnectionClosed:
|
||||
print("Connection closed by server.")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
asyncio.run(rtds_stream())
|
||||
except KeyboardInterrupt:
|
||||
print("Stream stopped.")
|
||||
Reference in New Issue
Block a user