{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "84687e61-c9ec-443f-990f-39f01f1ce867",
   "metadata": {},
   "source": [
    "# Real-time processing: Signal Generation"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "414daec9-0748-44a5-9166-5671bdf8cc8c",
   "metadata": {},
   "source": [
    "We'll compute golden cross signals using 50-second and 200-second moving averages\n",
    "\n",
    "- 'Entries' is set to 1 when the short-term moving average goes above the long term (i.e., a signal to buy)\n",
    "- 'Exits' is set to 1 on when the short-term moving average goes below the long term (i.e., a signal to sell)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a86a8fb-57a7-4105-adf1-8e0157f70d93",
   "metadata": {},
   "outputs": [],
   "source": [
    "import onetick.py as otp\n",
    "\n",
    "trd = otp.DataSource(tick_type='TRD', schema={'PRICE': float})\n",
    "trd = trd[['PRICE']]\n",
    "\n",
    "trd = trd.agg({'short': otp.agg.mean('PRICE')}, bucket_interval=60, running=True, all_fields=True)\n",
    "trd = trd.agg({'long': otp.agg.mean('PRICE')}, bucket_interval=60 * 5, running=True, all_fields=True)\n",
    "\n",
    "trd['buy'] = (trd['short'][-1] < trd['long'][-1]) & (trd['short'] > trd['long'])\n",
    "trd['sell'] = (trd['short'][-1] > trd['long'][-1]) & (trd['short'] < trd['long'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b97e5c06-cd39-4bbe-a373-90b6b5b7f4da",
   "metadata": {},
   "source": [
    "We define a callback that for every tick (i.e., on every trade) will\n",
    "\n",
    "- print a '.' if there is no signal\n",
    "- print out the tick followed by 'BUY' on an entry signal\n",
    "- print out the tick followed by 'SELL' on an exit signal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "df7199cf-01a1-4e80-85fb-18c39a1f9c45",
   "metadata": {},
   "outputs": [],
   "source": [
    "class GoldenCrossCallback(otp.CallbackBase):\n",
    "    def process_tick(self, tick, time):\n",
    "        if not tick['buy'] and not tick['sell']:\n",
    "            # print('.', end='')\n",
    "            return\n",
    "        # print()\n",
    "        # print()\n",
    "        print(time, tick)\n",
    "        if tick['buy']:\n",
    "            print('BUY')\n",
    "        if tick['sell']:\n",
    "            print('SELL')\n",
    "        print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e23ceca7-5e78-4f47-a98e-0c5d64077fd6",
   "metadata": {},
   "source": [
    "The query will run continuously with the output printed as the events happen\n",
    "if the database and start/end times are set accordingly (see the commented out lines).\n",
    "With the US_COMP_SAMPLE database used and the time interval set in the past, the query will work in \"historical\" mode."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d0792dd6-862e-446f-9197-3ee287b1a719",
   "metadata": {},
   "outputs": [],
   "source": [
    "# timestamps appear in GMT\n",
    "cb = GoldenCrossCallback()\n",
    "otp.run(trd,\n",
    "        callback=cb, running=True,\n",
    "        symbols='US_COMP_SAMPLE::AAPL',\n",
    "        start=otp.dt(2024, 2, 1, 10), end=otp.dt(2024, 2, 1, 11),\n",
    "        # symbols='US_COMP:AAPL',\n",
    "        # start=otp.dt.now(), end=otp.dt.now() + otp.Day(1),\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.9.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
