Skip to content

Commit

Permalink
moved strat stuff into one file so to not deal with imports
Browse files Browse the repository at this point in the history
  • Loading branch information
AxelGard committed Mar 24, 2024
1 parent b2bbea1 commit 97431a1
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 167 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ You should of course use your own strategy, but as an example.

```python
import cira
from cira.strategy.strategy import Randomness
from cira.strategy.backtest import back_test
from cira.strategy import Randomness
from cira.strategy import back_test
from datetime import datetime
import pandas as pd

Expand Down
124 changes: 122 additions & 2 deletions cira/strategy/backtest.py → cira/strategy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,95 @@
from typing import List
import pickle
import pandas as pd
import numpy as np
from typing import List
from .strategy import Strategy, ByAndHold
import random
import schedule
import time


class Strategy:
def __init__(self, name) -> None:
self.name = name

def iterate(
self,
feature_data: pd.DataFrame,
prices: pd.DataFrame,
portfolio: np.ndarray,
cash=float,
) -> np.ndarray:
"""
Takes in feature data, then returns allocation prediction.
"""
raise NotImplementedError

def save(self, file_path):
"""
Save strategy to pickle file
usage:
strategy.fit(train_data)
strategy.save('./model.pkl')
"""
with open(file_path, "wb") as file:
pickle.dump(self, file)

@classmethod
def load(cls, file_path):
"""
Load in strategy from pickle file
usage:
strategy = Strategy.load('./model.pkl')
predictions = strategy.predict(test_data)
"""
with open(file_path, "rb") as file:
return pickle.load(file)


class Randomness(Strategy):
def __init__(self, lower: int = -1, upper: int = 1, seed=0) -> None:
super().__init__(name="Randomness")
random.seed(seed)
self.a = lower
self.b = upper
self.allocation = []

def iterate(
self,
feature_data: pd.DataFrame,
prices: pd.DataFrame,
portfolio: np.ndarray,
cash=float,
) -> np.ndarray:
al = np.array(
[random.randint(self.a, self.b) for _ in range(len(prices.keys()))]
)
self.allocation.append(al)
return al


class ByAndHold(Strategy):
def __init__(self) -> None:
super().__init__(name="ByAndHold")
self.is_first = True
self.allocation = []

def iterate(
self,
feature_data: pd.DataFrame,
prices: pd.DataFrame,
portfolio: np.ndarray,
cash=float,
) -> np.ndarray:
if self.is_first:
self.is_first = False
amount = cash / len(prices.keys())
amount *= 0.96
al = (amount // prices.values).astype(np.int64)[0]
self.allocation.append(al)
return al
al = np.array([0] * len(prices.keys()))
self.allocation.append(al)
return al


FEE_RATE = 0.004 # this is what alpaca takes
Expand Down Expand Up @@ -104,3 +192,35 @@ def back_test_against_buy_and_hold(
capital=capital,
use_fees=use_fees,
)


class Scheduler:
def __init__(self) -> None:
pass

def add_daily_job(self, func_name) -> None:
schedule.every(1).days.do(func_name)

def add_daily_job_at(self, func_name, time_HM: str = "12:00") -> None:
schedule.every().day.at(time_HM).do(func_name)

def add_hour_job(self, func_name) -> None:
schedule.every(1).hour.do(func_name)

def add_minute_job(self, func_name) -> None:
schedule.every(1).minute.do(func_name)

def add_daily_job_at_time_EDT(self, func_name, time_HM: str = "12:00") -> None:
schedule.every().day.at(time_HM, "America/New_York").do(func_name)

def get_all_jobs(self):
return schedule.jobs

def clear_all_jobs(self) -> None:
schedule.clear()

def run(self):
"""runs the scheduler for ever"""
while True:
schedule.run_pending()
time.sleep(1)
4 changes: 0 additions & 4 deletions cira/strategy/__init__.py

This file was deleted.

34 changes: 0 additions & 34 deletions cira/strategy/scheduler.py

This file was deleted.

90 changes: 0 additions & 90 deletions cira/strategy/strategy.py

This file was deleted.

40 changes: 5 additions & 35 deletions examples/linear.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@
"from typing import List\n",
"from pandas import DataFrame\n",
"\n",
"from cira.strategy.strategy import Strategy\n",
"from cira.strategy import Strategy\n",
"\n",
"\n",
"class MyStrat(Strategy):\n",
Expand Down Expand Up @@ -330,7 +330,7 @@
}
],
"source": [
"from cira.strategy.backtest import back_test_against_buy_and_hold as back_test\n",
"from cira.strategy import back_test_against_buy_and_hold as back_test\n",
"\n",
"strat = MyStrat(model, risk=0.05)\n",
"prices_df = my_dataframe = pd.DataFrame(test_data[target], columns=['close'])\n",
Expand Down Expand Up @@ -455,16 +455,7 @@
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2024-03-04 20:40:28.480870 new position size: [-93] of symbol MSFT\n",
"ratio:1.0076733\n"
]
}
],
"outputs": [],
"source": [
"trade()"
]
Expand All @@ -473,31 +464,10 @@
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[Every 1 day at 20:36:00 do trade() (last run: [never], next run: 2024-03-04 20:36:00)]\n",
"[-93]\n"
]
},
{
"ename": "KeyboardInterrupt",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[58], line 8\u001b[0m\n\u001b[1;32m 5\u001b[0m scheduler\u001b[38;5;241m.\u001b[39madd_daily_job_at(trade, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m20:36\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28mprint\u001b[39m(scheduler\u001b[38;5;241m.\u001b[39mget_all_jobs())\n\u001b[0;32m----> 8\u001b[0m \u001b[43mscheduler\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/Programs/repositories/cira/cira/strategy/scheduler.py:34\u001b[0m, in \u001b[0;36mScheduler.run\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 32\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 33\u001b[0m schedule\u001b[38;5;241m.\u001b[39mrun_pending()\n\u001b[0;32m---> 34\u001b[0m \u001b[43mtime\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msleep\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
]
}
],
"outputs": [],
"source": [
"\n",
"from cira.strategy.scheduler import Scheduler\n",
"from cira.strategy import Scheduler\n",
"\n",
"scheduler = Scheduler()\n",
"scheduler.clear_all_jobs()\n",
Expand Down

0 comments on commit 97431a1

Please sign in to comment.