Skip to content

Commit

Permalink
Minor updates 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack Song committed Jun 11, 2019
1 parent b239d15 commit 3d016a7
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 3 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ This mini QuantTrading project will have the following features:

### TradeStrategy x 2

#### Strategy 1: Trend Following.
#### Strategy 1: Trend Following

When price rises above an absolute threshold `p_change_threshold` percent, default to 2%.

Buy and hold for `hold_stock_threshold` days, default to 20.

[Source File](./alpha/strategies/strategy_1.ipynb) & [Demo Usage](./alpha/strategies/strategy_1_usage.ipynb).

#### Strategy 2: Reversion.
#### Strategy 2: Mean Reversion

When price falls consecutively for two days, and cumulatively more than `p_change_threshold` percent in total, default to 10%.

Expand Down
2 changes: 1 addition & 1 deletion alpha/strategies/strategy_2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"cell_type": "code",
"execution_count": 22,
"outputs": [],
"source": "# %%file strategy_2.py\n\nimport import_ipynb\nfrom strategy_base import TradeStrategyBase\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nclass TradeStrategy2(TradeStrategyBase):\n \"\"\"\n Trade Strategy 2: Reversion Strategy. \n When price falls two days in a row, and cumulatively more than x percent (_p_change_threshold) in total, default to 10%.\n Buy and hold for a number of days (_hold_stock_threshold) days, default to 20. \n \"\"\"\n # Absolute threshold for buy in\n _p_change_threshold \u003d 10\n # Number of days to hold after Buy\n _hold_stock_threshold \u003d 10\n \n def __init__(self, p_change_threshold:float \u003d 10.0, hold_stock_threshold:int \u003d 10, should_log:bool \u003d False, should_plot:bool \u003d False, axs \u003d None):\n \"\"\"\n Initialize Strategy with given parameters\n :type p_change_threshold: float\n :type hold_stock_threshold: int \n :type should_log: bool\n :type should_plot: bool\n :param p_change_threshold: Absolute threshold for a stock to rise in two days. E.g. 7.5% \u003d 7.5 \n :param hold_stock_threshold: Number of days to hold a stock. E.g. 20 days \u003d 20\n :param should_log Whether or not log the strategy\n :param should_plot Whether or not plot the strategy\n \"\"\"\n self._p_change_threshold \u003d p_change_threshold\n self._hold_stock_threshold \u003d hold_stock_threshold\n self._should_log \u003d should_log\n self._should_plot \u003d should_plot\n self._axs \u003d axs\n \n self._held_tradedays \u003d pd.DataFrame()\n self._previous_tradeday \u003d None\n self._held_period_days \u003d 0\n \n def trade(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n Perform Analysis, Decide on Trade, and Execute Trade\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n :return: \n \"\"\"\n \n \"\"\"\n Firstly, Increment holding date count\n \"\"\"\n if self._held_period_days !\u003d 0:\n # Increment date\n self._held_period_days +\u003d 1\n # Is currently holding, attach new tradeday in DataFrame\n self._held_tradedays \u003d self._held_tradedays.append(tradeday)\n \n \"\"\"\n Secondly, Buying\n \"\"\"\n if self._evaluate_buying(date\u003ddate,\n tradeday\u003dtradeday):\n self._execute_buying(date\u003ddate,\n tradeday\u003dtradeday)\n \n \"\"\"\n Lastly, Selling\n \"\"\"\n if self._evaluate_selling(date\u003ddate,\n tradeday\u003dtradeday):\n self._execute_selling(date\u003ddate,\n tradeday\u003dtradeday)\n \n def _evaluate_buying(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n Evaluate whether or not BUY should be executed\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n \"\"\"\n trade_day: pd.Series \u003d tradeday.copy() # Create a copy() in case we need to change it.\n if self._held_period_days \u003d\u003d 0 and self._previous_tradeday is not None:\n # trade_day.change \u003c 0 : Tells if price dropped\n is_today_price_down \u003d trade_day.p_change \u003c 0\n # Check if yesterday was down\n is_yesterday_price_down \u003d self._previous_tradeday.p_change \u003c 0\n \n # Sum of all drops\n total_down_rate \u003d trade_day.p_change + self._previous_tradeday.p_change\n \n # Set previous_tradeday to today\n self._previous_tradeday \u003d tradeday\n \n if is_today_price_down and \\\n is_yesterday_price_down and \\\n np.abs(total_down_rate) \u003e self._p_change_threshold:\n return True\n else:\n return False\n else:\n # Set previous_tradeday to today\n self._previous_tradeday \u003d tradeday\n return False\n \n def _execute_buying(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n How BUY should be executed\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n \"\"\"\n if self._should_log:\n print(\"Bought on {} at ${}.\".format(date, tradeday.close))\n self._held_period_days +\u003d 1 # Start holding date count\n self._held_tradedays \u003d pd.DataFrame(tradeday).T # Transpose of Series\n self._last_buy_date \u003d date\n\n def _evaluate_selling(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n Evaluate whether or not SELL should be executed\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n \"\"\"\n if self._held_period_days \u003e\u003d self._hold_stock_threshold:\n # When holding period exceeds hold_stock_threshold, sell stocks\n return True\n else:\n return False\n \n def _execute_selling(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n How SELL should be executed\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n \"\"\" \n if self._should_log:\n print(\"Sold on {} at ${}.\".format(date, tradeday.close))\n if self._should_plot:\n self._plot_trade(axs\u003dself._axs,\n buy_date\u003dself._last_buy_date, \n sell_date\u003ddate)\n self._previous_tradeday \u003d None # Reset last tradeday\n self._held_period_days \u003d 0 # Reset holding count \n self._last_buy_date \u003d None # Reset last buy date\n\n def _plot_trade(self, axs, buy_date, sell_date):\n\n print(\"Todo: Plotting {} {}\".format(buy_date, sell_date))\n\n # buy_tradeday \u003d self._held_tradedays[buy_date.date()]\n # sell_tradeday \u003d self._held_tradedays[sell_date.date()]\n # print(\"Bought at {}, Sold at {}\".format(buy_tradeday.close, sell_tradeday.close))\n\n # drawer \u003d plt if axs is None else axs\n # \n # # Mark red for up and green for down, slicing using start and end\n # if sell_tradeday.close \u003c buy_tradeday.close:\n # drawer.fill_between(self._held_tradedays.index[buy_date:sell_date], 0,\n # self._held_tradedays[\u0027close\u0027][buy_date:sell_date], color\u003d\u0027red\u0027,\n # alpha\u003d.38)\n # is_win \u003d False\n # else:\n # drawer.fill_between(amex_df.index[buy_date:sell_date], 0,\n # amex_df[\u0027close\u0027][buy_date:sell_date], color\u003d\u0027green\u0027,\n # alpha\u003d.38)\n # is_win \u003d True\n # \n # return is_win\n \n @property\n def trade_profit(self):\n if \u0027p_change\u0027 in self._held_tradedays.columns:\n profit_array \u003d self._held_tradedays.p_change/100 + 1\n profit_rate \u003d np.product(profit_array)-1\n return profit_rate\n else:\n return 0\n \n @property\n def p_change_threshold(self):\n return self._p_change_threshold\n \n @property\n def keep_stock_threshold(self):\n return self._hold_stock_threshold\n ",
"source": "# %%file strategy_2.py\n\nimport import_ipynb\nfrom strategy_base import TradeStrategyBase\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nclass TradeStrategy2(TradeStrategyBase):\n \"\"\"\n Trade Strategy 2: Mean Reversion. \n When price falls two days in a row, and cumulatively more than x percent (_p_change_threshold) in total, default to 10%.\n Buy and hold for a number of days (_hold_stock_threshold) days, default to 20. \n \"\"\"\n # Absolute threshold for buy in\n _p_change_threshold \u003d 10\n # Number of days to hold after Buy\n _hold_stock_threshold \u003d 10\n \n def __init__(self, p_change_threshold:float \u003d 10.0, hold_stock_threshold:int \u003d 10, should_log:bool \u003d False, should_plot:bool \u003d False, axs \u003d None):\n \"\"\"\n Initialize Strategy with given parameters\n :type p_change_threshold: float\n :type hold_stock_threshold: int \n :type should_log: bool\n :type should_plot: bool\n :param p_change_threshold: Absolute threshold for a stock to rise in two days. E.g. 7.5% \u003d 7.5 \n :param hold_stock_threshold: Number of days to hold a stock. E.g. 20 days \u003d 20\n :param should_log Whether or not log the strategy\n :param should_plot Whether or not plot the strategy\n \"\"\"\n self._p_change_threshold \u003d p_change_threshold\n self._hold_stock_threshold \u003d hold_stock_threshold\n self._should_log \u003d should_log\n self._should_plot \u003d should_plot\n self._axs \u003d axs\n \n self._held_tradedays \u003d pd.DataFrame()\n self._previous_tradeday \u003d None\n self._held_period_days \u003d 0\n \n def trade(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n Perform Analysis, Decide on Trade, and Execute Trade\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n :return: \n \"\"\"\n \n \"\"\"\n Firstly, Increment holding date count\n \"\"\"\n if self._held_period_days !\u003d 0:\n # Increment date\n self._held_period_days +\u003d 1\n # Is currently holding, attach new tradeday in DataFrame\n self._held_tradedays \u003d self._held_tradedays.append(tradeday)\n \n \"\"\"\n Secondly, Buying\n \"\"\"\n if self._evaluate_buying(date\u003ddate,\n tradeday\u003dtradeday):\n self._execute_buying(date\u003ddate,\n tradeday\u003dtradeday)\n \n \"\"\"\n Lastly, Selling\n \"\"\"\n if self._evaluate_selling(date\u003ddate,\n tradeday\u003dtradeday):\n self._execute_selling(date\u003ddate,\n tradeday\u003dtradeday)\n \n def _evaluate_buying(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n Evaluate whether or not BUY should be executed\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n \"\"\"\n trade_day: pd.Series \u003d tradeday.copy() # Create a copy() in case we need to change it.\n if self._held_period_days \u003d\u003d 0 and self._previous_tradeday is not None:\n # trade_day.change \u003c 0 : Tells if price dropped\n is_today_price_down \u003d trade_day.p_change \u003c 0\n # Check if yesterday was down\n is_yesterday_price_down \u003d self._previous_tradeday.p_change \u003c 0\n \n # Sum of all drops\n total_down_rate \u003d trade_day.p_change + self._previous_tradeday.p_change\n \n # Set previous_tradeday to today\n self._previous_tradeday \u003d tradeday\n \n if is_today_price_down and \\\n is_yesterday_price_down and \\\n np.abs(total_down_rate) \u003e self._p_change_threshold:\n return True\n else:\n return False\n else:\n # Set previous_tradeday to today\n self._previous_tradeday \u003d tradeday\n return False\n \n def _execute_buying(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n How BUY should be executed\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n \"\"\"\n if self._should_log:\n print(\"Bought on {} at ${}.\".format(date, tradeday.close))\n self._held_period_days +\u003d 1 # Start holding date count\n self._held_tradedays \u003d pd.DataFrame(tradeday).T # Transpose of Series\n self._last_buy_date \u003d date\n\n def _evaluate_selling(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n Evaluate whether or not SELL should be executed\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n \"\"\"\n if self._held_period_days \u003e\u003d self._hold_stock_threshold:\n # When holding period exceeds hold_stock_threshold, sell stocks\n return True\n else:\n return False\n \n def _execute_selling(self, date:pd.Timestamp, tradeday: pd.Series):\n \"\"\"\n How SELL should be executed\n :type date: pd.Timestamp\n :type tradeday: pd.Series\n :param date: The pandas DataFrame date\n :param tradeday: The pandas DateFrame Series representing a trade day\n \"\"\" \n if self._should_log:\n print(\"Sold on {} at ${}.\".format(date, tradeday.close))\n if self._should_plot:\n self._plot_trade(axs\u003dself._axs,\n buy_date\u003dself._last_buy_date, \n sell_date\u003ddate)\n self._previous_tradeday \u003d None # Reset last tradeday\n self._held_period_days \u003d 0 # Reset holding count \n self._last_buy_date \u003d None # Reset last buy date\n\n def _plot_trade(self, axs, buy_date, sell_date):\n\n print(\"Todo: Plotting {} {}\".format(buy_date, sell_date))\n\n # buy_tradeday \u003d self._held_tradedays[buy_date.date()]\n # sell_tradeday \u003d self._held_tradedays[sell_date.date()]\n # print(\"Bought at {}, Sold at {}\".format(buy_tradeday.close, sell_tradeday.close))\n\n # drawer \u003d plt if axs is None else axs\n # \n # # Mark red for up and green for down, slicing using start and end\n # if sell_tradeday.close \u003c buy_tradeday.close:\n # drawer.fill_between(self._held_tradedays.index[buy_date:sell_date], 0,\n # self._held_tradedays[\u0027close\u0027][buy_date:sell_date], color\u003d\u0027red\u0027,\n # alpha\u003d.38)\n # is_win \u003d False\n # else:\n # drawer.fill_between(amex_df.index[buy_date:sell_date], 0,\n # amex_df[\u0027close\u0027][buy_date:sell_date], color\u003d\u0027green\u0027,\n # alpha\u003d.38)\n # is_win \u003d True\n # \n # return is_win\n \n @property\n def trade_profit(self):\n if \u0027p_change\u0027 in self._held_tradedays.columns:\n profit_array \u003d self._held_tradedays.p_change/100 + 1\n profit_rate \u003d np.product(profit_array)-1\n return profit_rate\n else:\n return 0\n \n @property\n def p_change_threshold(self):\n return self._p_change_threshold\n \n @property\n def keep_stock_threshold(self):\n return self._hold_stock_threshold\n ",
"metadata": {
"pycharm": {
"metadata": false,
Expand Down

0 comments on commit 3d016a7

Please sign in to comment.