diff --git a/README.md b/README.md index 50a83f2..8c05118 100644 --- a/README.md +++ b/README.md @@ -48,3 +48,15 @@ Run the following commands from the agents directory to run an ephemeral docker ./scripts/bash/build-docker.sh ./scripts/bash/run-docker-dev.sh ``` + +# Future + +This repo is intended to be an experimental developer toolkit. In order to productionize the system with capital, we recommend the following major projects begin to be developed: + +[ ] Backtesting +[ ] Papertrading + +Other major development endeavors that would support the current state of the system include: + +[ ] External embeddings +[ ] More news api sources diff --git a/ai/llm/executor.py b/ai/llm/executor.py index fab756c..f99c4b1 100644 --- a/ai/llm/executor.py +++ b/ai/llm/executor.py @@ -1,15 +1,20 @@ import os +import time +import json from dotenv import load_dotenv from langchain_core.messages import HumanMessage, SystemMessage from langchain_openai import ChatOpenAI +from langchain_openai import OpenAIEmbeddings from ai.llm import prompts from api.gamma import GammaMarketClient -from polymarket.agents.ai.llm.prompts import Prompter +from ai.llm.prompts import Prompter +from ai.rag.chroma import Chroma class Executor: + def __init__(self): load_dotenv() self.prompter = Prompter() @@ -18,7 +23,13 @@ def __init__(self): model="gpt-3.5-turbo", temperature=0, ) + self.llm_embedding_function = OpenAIEmbeddings(model="text-embedding-3-small") self.client = GammaMarketClient() + self.chroma = Chroma() + + self.local_data_directory = "./localDb" + if not os.path.isdir(self.local_data_directory): + os.mkdir(self.local_data_directory) def get_llm_response(self, user_input: str) -> str: system_message = SystemMessage(content=str(prompts.market_analyst)) @@ -47,8 +58,32 @@ def get_polymarket_llm(self, user_input: str) -> str: result = self.llm.invoke(messages) return result.content - def filter_events(self): - pass + def filter_events(self, events): + if not self.chroma: + # create local embedding for events + local_events_embedding_path = f"{self.local_data_directory}/events.json" + if os.path.isfile(self.local_data_directory): + os.remove(local_events_embedding_path) + with open(local_events_embedding_path, "w+") as output_file: + json.dump(events, output_file) + + # load embedding into chroma + local_db = Chroma( + persist_directory=self.local_data_directory, + embedding_function=self.llm_embedding_function, + ) + + # query using a prompt + prompt = self.prompter.filter_events() + print(prompt) + response_docs = local_db.similarity_search_with_score(query=prompt) + print(response_docs) + return response_docs + + else: + self.chroma.create_local_markets_rag() + prompt = self.prompter.filter_events() + return self.chroma.query_local_markets_rag(prompt) def filter_markets(self): pass diff --git a/ai/llm/prompts.py b/ai/llm/prompts.py index e5c728e..5b93ca0 100644 --- a/ai/llm/prompts.py +++ b/ai/llm/prompts.py @@ -121,7 +121,7 @@ def polymarket_analyst_api(self) -> str: def filter_events(self) -> str: return ( - self.polymarket_analyst_api(self) + self.polymarket_analyst_api() + """ Filter events for the ones you will be best at trading on profitably. diff --git a/ai/rag/chroma.py b/ai/rag/chroma.py index cbc996c..9612909 100644 --- a/ai/rag/chroma.py +++ b/ai/rag/chroma.py @@ -8,14 +8,14 @@ from api.gamma import GammaMarketClient -class PolymarketRAG: +class Chroma: def __init__(self, local_db_directory=None, embedding_function=None) -> None: self.gamma_client = GammaMarketClient() self.local_db_directory = local_db_directory self.embedding_function = embedding_function def load_json_from_local( - self, json_file_path=None, vector_db_directory="./local_db" + self, json_file_path=None, vector_db_directory="./localDb" ): loader = JSONLoader( file_path=json_file_path, jq_schema=".[].description", text_content=False @@ -29,7 +29,7 @@ def load_json_from_local( return db2 - def create_local_markets_rag(self, local_directory="./local_db"): + def create_local_markets_rag(self, local_directory="./localDb"): all_markets = self.gamma_client.get_all_current_markets() if not os.path.isdir(local_directory): @@ -44,7 +44,7 @@ def create_local_markets_rag(self, local_directory="./local_db"): json_file_path=local_file_path, vector_db_directory=local_directory ) - def query_local_markets_rag(self, local_directory=None, query=None): + def query_local_markets_rag(self, query=None, local_directory="./local_db"): embedding_function = OpenAIEmbeddings(model="text-embedding-3-small") local_db = Chroma( persist_directory=local_directory, embedding_function=embedding_function diff --git a/api/polymarket.py b/api/polymarket.py index 3dace20..9a56ab7 100644 --- a/api/polymarket.py +++ b/api/polymarket.py @@ -22,8 +22,8 @@ from py_clob_client.clob_types import OrderArgs from py_clob_client.order_builder.constants import BUY -from api.polymarket.types import SimpleMarket -from api.polymarket.types import SimpleEvent +from api.types import SimpleMarket +from api.types import SimpleEvent load_dotenv() @@ -45,8 +45,8 @@ def __init__(self): self.exchange_address = "0x4bfb41d5b3570defd03c39a9a4d8de6bd8b8982e" self.neg_risk_exchange_address = "0xC5d563A36AE78145C45a50134d48A1215220f80a" - self._init_api_keys() - self._init_approvals(True) + # self._init_api_keys() + # self._init_approvals(True) def _init_api_keys(self): self.client = ClobClient( diff --git a/jobs/scheduler.py b/jobs/scheduler.py index 4c350ca..60b378c 100644 --- a/jobs/scheduler.py +++ b/jobs/scheduler.py @@ -1,15 +1,15 @@ import datetime as dt import time -from polymarket.agents.lib.trade import Trader +from lib.trade import Trader -from polymarket.agents.lib.history import record_history -from polymarket.agents.lib.refresh import refresh_trades +from lib.history import record_history +from lib.refresh import refresh_trades from scheduler import Scheduler from scheduler.trigger import Monday -class Scheduler: +class MetaScheduler: def __init__(self): self.trader = Trader() self.schedule = Scheduler() @@ -22,11 +22,14 @@ def start(self): class TradingAgent(Scheduler): def __init__(self): - super() self.trader = Trader() - self.weekly(Monday(), self.trader.one_best_trade) - self.daily(dt.time(hour=12), refresh_trades) - self.hourly(dt.time(minute=30), record_history) + self.schedule = Scheduler() + self.schedule.weekly(Monday(), self.trader.one_best_trade) + self.schedule.daily(dt.time(hour=12), refresh_trades) + self.schedule.hourly(dt.time(minute=30), record_history) + + def trade(self): + self.trader.one_best_trade() # TODO: add task objects for generalized schedule management infrastructure diff --git a/lib/creator.py b/lib/creator.py index ef7efff..dee7fcb 100644 --- a/lib/creator.py +++ b/lib/creator.py @@ -1,6 +1,6 @@ -from polymarket.agents.ai.llm.executor import Executor as Agent -from polymarket.agents.api.polymarket import Polymarket -from polymarket.agents.data.newspaper import Newspaper +from ai.llm.executor import Executor as Agent +from api.polymarket import Polymarket +from data.newspaper import Newspaper class Creator: diff --git a/lib/trade.py b/lib/trade.py index ec3488f..3a7c4df 100644 --- a/lib/trade.py +++ b/lib/trade.py @@ -1,6 +1,8 @@ -from polymarket.agents.ai.llm.executor import Executor as Agent -from polymarket.agents.api.polymarket import Polymarket -from polymarket.agents.data.newspaper import Newspaper +from ai.llm.executor import Executor as Agent +from api.polymarket import Polymarket +from data.newspaper import Newspaper + +import pdb class Trader: @@ -19,17 +21,23 @@ def one_best_trade(self): then executes that trade without any human intervention """ + + print("1. GETTING ALL EVENTS polymarket.get_all_events()") events = self.polymarket.get_all_events() - events = self.agent.filter_events() - markets = [self.polymarket.get_market(e) for e in events] - markets = self.agent.filter_markets() - orderbooks = [self.polymarket.get_orderbooks(m) for m in markets] - orderbooks = self.agent.filter_orderbooks() - best_trade = self.agent.source_best_trade( - events, markets, orderbooks, self.newspaper - ) - formatted_best_trade = self.agent.format_trade_prompt_for_execution(best_trade) - return self.polymarket.execute_order(**formatted_best_trade) + print("2. GOT EVENTS. len(events) = ", len(events)) + print("3. FILTERING EVENTS ...") + pdb.set_trace() + events = self.agent.filter_events([x.json() for x in events]) + print("4. GOT BEST EVENTS: ", events) + # markets = [self.polymarket.get_market(e) for e in events] + # markets = self.agent.filter_markets() + # orderbooks = [self.polymarket.get_orderbooks(m) for m in markets] + # orderbooks = self.agent.filter_orderbooks() + # best_trade = self.agent.source_best_trade( + # events, markets, orderbooks, self.newspaper + # ) + # formatted_best_trade = self.agent.format_trade_prompt_for_execution(best_trade) + # return self.polymarket.execute_order(**formatted_best_trade) def maintain_positions(self): pass diff --git a/scripts/python/cli.py b/scripts/python/cli.py index e627c16..f2c43ea 100644 --- a/scripts/python/cli.py +++ b/scripts/python/cli.py @@ -3,14 +3,14 @@ from api.polymarket import Polymarket from ai.llm import executor, prompts -from ai.rag.chroma import PolymarketRAG +from ai.rag.chroma import Chroma from data.news.newsapiorg.api import API as NewsApiCaller from jobs.scheduler import TradingAgent app = typer.Typer() polymarket = Polymarket() newsapi_client = NewsApiCaller() -polymarket_rag = PolymarketRAG() +polymarket_rag = Chroma() @app.command() @@ -118,12 +118,12 @@ def ask_polymarket_llm(user_input: str): @app.command() -def run_autonomous_trader(user_input: str): +def run_autonomous_trader(): """ Let an autonomous system trade for you. """ trader = TradingAgent() - trader.start() + trader.trade() if __name__ == "__main__": diff --git a/scripts/python/server.py b/scripts/python/server.py index 46743b7..22de752 100644 --- a/scripts/python/server.py +++ b/scripts/python/server.py @@ -1,3 +1,13 @@ +""" + +We envision decentralized agents being able to +communicate with one another as they decide trades. + +This server could also be used for observability of +decentralized agents trading performance. + +""" + from typing import Union from fastapi import FastAPI @@ -22,6 +32,3 @@ def read_trade(trade_id: int, q: Union[str, None] = None): @app.get("/markets/{market_id}") def read_market(market_id: int, q: Union[str, None] = None): return {"market_id": market_id, "q": q} - - -# post new prompt