{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ea1605ab-9dc6-4f90-944e-4355dcf3aab7",
   "metadata": {},
   "source": [
    "# Shared Context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3ee55c54-eee8-4c3f-bf15-15df94084cc6",
   "metadata": {
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from typing import Any, List\n",
    "from urllib.parse import urlparse\n",
    "import re\n",
    "import json\n",
    "import textwrap\n",
    "REQUEST: Any\n",
    "\n",
    "def parse_url(url):\n",
    "    parsed_url = urlparse(url)\n",
    "    scheme = parsed_url.scheme\n",
    "    hostname = parsed_url.netloc\n",
    "    path = parsed_url.path\n",
    "    match = re.search(r'([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})', path, re.IGNORECASE)\n",
    "    project_id = match.group(1) if match else None    \n",
    "    return scheme, hostname, project_id\n",
    "\n",
    "\n",
    "scheme, hostname, project_id = parse_url(spy.utils.get_data_lab_project_url())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "64c7e209-f611-4f41-9e69-c95628cd4066",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Keywise Numeric Negation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "584e64d9-0066-43a4-a6c8-39400782f6e9",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# This example takes one NUMERIC signal as input and negates the\n",
    "# values from it.\n",
    "# It is an example of doing calculations on one key of data.\n",
    "\n",
    "def compute_keywise_numeric_negation(signal_data_types, signal_data):\n",
    "    return \\\n",
    "        [sample[0] for sample in signal_data], \\\n",
    "        [-sample[1] for sample in signal_data]\n",
    "\n",
    "def get_variables_keywise_numeric_negation():\n",
    "    metadata = {\n",
    "        # Type of input mode.\n",
    "        # either 'KEYWISE' or 'WINDOW'\n",
    "        \"inputMode\": \"KEYWISE\",\n",
    "        \n",
    "        # Type of output signal.\n",
    "        # either 'NUMERIC' or 'STRING'\n",
    "        \"outputType\": \"NUMERIC\",\n",
    "        \n",
    "        # Dictionary of function details.\n",
    "        # Name (required): name of the function.\n",
    "        # Documentation (optional): documentation for the function.\n",
    "        # Formula (required): the Formula snippet that will be executed.\n",
    "        #   It must contain a call to\n",
    "        #   addOnCalculation or addOnCalculationOnWindow\n",
    "        #   with \"@@scriptId@@ as the first parameter.\n",
    "        #\n",
    "        #   Other Seeq operators can be used within the snippet. Other\n",
    "        #   parameters can be passed to the addOnCalculation or used by\n",
    "        #   Seeq operators in the complete formula.\n",
    "        # Parameters (required): described above.\n",
    "        # Examples (optional): described above.\n",
    "        #\n",
    "        # @@scriptId@@ is a placeholder and will be replaced with\n",
    "        # the correct identifier string automatically.\n",
    "        \"udfDefinition\": {\n",
    "            \"Name\": \"numericNegation\",\n",
    "            \"Documentation\": textwrap.dedent(\"\"\"\n",
    "                This highly unique function can negate any numeric signal\n",
    "                using the power of add-on calculations.\n",
    "            \"\"\").strip(),\n",
    "            \"Formula\": \"addOnCalculation(@@scriptId@@, 'NUMERIC', $signal)\",\n",
    "            \n",
    "            # List of parameters. Each dictionary corresponds to a parameter.\n",
    "            # There are four fields.\n",
    "            # Name (required) - the string name of the parameter\n",
    "            # Formula (optional) - the formula snippet that determines\n",
    "            #   the type and metadata of the parameter.\n",
    "            #   If the Formula is set, the DefaultValue must NOT be set.\n",
    "            # Optional (optional) - boolean, if this parameter is Optional.\n",
    "            #   If not set, the parameter is assumed to be required.\n",
    "            # DefaultValue (optional) - a default value to be used if none\n",
    "            # is provided.\n",
    "            #   Can only be set if Optional is true.\n",
    "            #   If set, the type of the parameter is determined by the type\n",
    "            #   of the default value provided. Do not use with Formula.\n",
    "\n",
    "            # Parameters must be ordered as\n",
    "            # 1. Mandatory\n",
    "            # 2. Optional with default value\n",
    "            # 3. Optional without default value\n",
    "            #\n",
    "            # At least one parameter is required.\n",
    "            \"Parameters\": [\n",
    "                {\"Name\": \"signal\", \"Formula\": \"sinusoid()\"}\n",
    "            ],\n",
    "            \n",
    "            # List of examples. Each dictionary corresponds to an example.\n",
    "            # Each example must have a Formula.\n",
    "            # A Description is optional.\n",
    "\n",
    "            # Different examples can describe different variants of the\n",
    "            # Add-on Function.\n",
    "            #\n",
    "            # @@functionName@@ is a placeholder and will be replaced automatically\n",
    "            # with packageName_functionName where packageName is defined by\n",
    "            # the folder this script is placed in and functionName is\n",
    "            # defined below in function_details.\n",
    "            \"Examples\": [\n",
    "                {\"Formula\": \"$series.@@functionName@@()\", \"Description\": \"Negate\"}\n",
    "            ],\n",
    "        }\n",
    "    }\n",
    "\n",
    "    url = f\"{scheme}://{hostname}/data-lab/{project_id}/functions/notebooks/api/endpoints/compute-numeric-negation\"\n",
    "    return url, metadata"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "092e072e-c7e1-4797-8093-e3dadf1db085",
   "metadata": {},
   "source": [
    "# Keywise Two Signals Running Sum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fff297c8-f3a1-456b-abc6-554e7c171f09",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# This example takes two NUMERIC signals as input, sums them,\n",
    "# and computes the running sum over each day.\n",
    "\n",
    "def compute_keywise_two_signals_running_sum(signal_data_types, signal_data):\n",
    "    return \\\n",
    "        [sample[0] for sample in signal_data], \\\n",
    "        [sum(sample[1:]) for sample in signal_data]\n",
    "\n",
    "def get_variables_keywise_two_signals_running_sum():\n",
    "    metadata = {\n",
    "        # Type of input mode.\n",
    "        # either 'KEYWISE' or 'WINDOW'\n",
    "        \"inputMode\": \"KEYWISE\",\n",
    "        \n",
    "        # Type of output signal.\n",
    "        # either 'NUMERIC' or 'STRING'\n",
    "        \"outputType\": \"NUMERIC\",\n",
    "        \n",
    "        # Dictionary of function details.\n",
    "        # Name (required): name of the function.\n",
    "        # Documentation (optional): documentation for the function.\n",
    "        # Formula (required): the Formula snippet that will be executed.\n",
    "        #   It must contain a call to\n",
    "        #   addOnCalculation or addOnCalculationOnWindow\n",
    "        #   with \"@@scriptId@@ as the first parameter.\n",
    "        #\n",
    "        #   Other Seeq operators can be used within the snippet. Other\n",
    "        #   parameters can be passed to the addOnCalculation or used by\n",
    "        #   Seeq operators in the complete formula.\n",
    "        # Parameters (required): described above.\n",
    "        # Examples (optional): described above.\n",
    "        #\n",
    "        # @@scriptId@@ is a placeholder and will be replaced with\n",
    "        # the correct identifier string automatically.\n",
    "        \"udfDefinition\": {\n",
    "            \"Name\": \"runningSum\",\n",
    "            \"Documentation\": textwrap.dedent(\"\"\"\n",
    "                This highly unique function can compute \n",
    "                daily running sums of two signals.\n",
    "            \"\"\").strip(),\n",
    "            \"Formula\": \"addOnCalculation(@@scriptId@@, 'NUMERIC', $signal1, $signal2).runningSum(days())\",\n",
    "            \n",
    "            # List of parameters. Each dictionary corresponds to a parameter.\n",
    "            # There are four fields.\n",
    "            # Name (required) - the string name of the parameter\n",
    "            # Formula (optional) - the formula snippet that determines\n",
    "            #   the type and metadata of the parameter.\n",
    "            #   If the Formula is set, the DefaultValue must NOT be set.\n",
    "            # Optional (optional) - boolean, if this parameter is Optional.\n",
    "            #   If not set, the parameter is assumed to be required.\n",
    "            # DefaultValue (optional) - a default value to be used if none\n",
    "            # is provided.\n",
    "            #   Can only be set if Optional is true.\n",
    "            #   If set, the type of the parameter is determined by the type\n",
    "            #   of the default value provided. Do not use with Formula.\n",
    "\n",
    "            # Parameters must be ordered as\n",
    "            # 1. Mandatory\n",
    "            # 2. Optional with default value\n",
    "            # 3. Optional without default value\n",
    "            #\n",
    "            # At least one parameter is required.\n",
    "            \"Parameters\": [\n",
    "                {'Name': 'signal1', 'Formula': 'sinusoid()'},\n",
    "                {'Name': 'signal2', 'Formula': 'sinusoid()'}\n",
    "            ],\n",
    "            \n",
    "            # List of examples. Each dictionary corresponds to an example.\n",
    "            # Each example must have a Formula.\n",
    "            # A Description is optional.\n",
    "            #\n",
    "            # Different examples can describe different variants of the\n",
    "            # Add-on Function.\n",
    "            #\n",
    "            # @@functionName@@ is a placeholder and will be replaced automatically\n",
    "            # with packageName_functionName where packageName is defined by\n",
    "            # the folder this script is placed in and functionName is\n",
    "            # defined below in function_details.\n",
    "            \"Examples\": [\n",
    "                {\n",
    "                    'Formula': '@@functionName@@($series1, $series2)',\n",
    "                    'Description': 'Computes daily running sums for the sum of $series1 and $series2.'\n",
    "                }\n",
    "            ],\n",
    "        }\n",
    "    }\n",
    "\n",
    "    url = f\"{scheme}://{hostname}/data-lab/{project_id}/functions/notebooks/api/endpoints/compute-two-signals-running-sum\"\n",
    "    return url, metadata"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbbb9f74-cb84-4fcb-a8f3-d4db296cc260",
   "metadata": {},
   "source": [
    "# Keywise Two Signals Multiply With Offset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c793c2fd-5c17-47f4-bdae-e760faf0efa9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# The Add-on Function takes 4 inputs, 2 signals that are passed to the\n",
    "# Add-on Calculation script and 2 optional scalars with default values.\n",
    "# The signals are multiplied together keywise, scaled by a factor\n",
    "# of the first scalar and offset by the second scalar.\n",
    "\n",
    "def compute_two_signals_multiply_with_offset(signal_data_types, signal_data):\n",
    "    return \\\n",
    "        [sample[0] for sample in signal_data], \\\n",
    "        [sample[1] * sample[2] for sample in signal_data]\n",
    "\n",
    "def get_variables_keywise_two_signals_multiply_with_offset():\n",
    "    metadata = {\n",
    "        # Type of input mode.\n",
    "        # either 'KEYWISE' or 'WINDOW'\n",
    "        \"inputMode\": \"KEYWISE\",\n",
    "        \n",
    "        # Type of output signal.\n",
    "        # either 'NUMERIC' or 'STRING'\n",
    "        \"outputType\": \"NUMERIC\",\n",
    "        \n",
    "        # Dictionary of function details.\n",
    "        # Name (required): name of the function.\n",
    "        # Documentation (optional): documentation for the function.\n",
    "        # Formula (required): the Formula snippet that will be executed.\n",
    "        #   It must contain a call to\n",
    "        #   addOnCalculation or addOnCalculationOnWindow\n",
    "        #   with \"@@scriptId@@ as the first parameter.\n",
    "        #\n",
    "        #   Other Seeq operators can be used within the snippet. Other\n",
    "        #   parameters can be passed to the addOnCalculation or used by\n",
    "        #   Seeq operators in the complete formula.\n",
    "        # Parameters (required): described above.\n",
    "        # Examples (optional): described above.\n",
    "        #\n",
    "        # @@scriptId@@ is a placeholder and will be replaced with\n",
    "        # the correct identifier string automatically.\n",
    "        \"udfDefinition\": {\n",
    "            \"Name\": \"multiplyWithOffset\",\n",
    "            \"Documentation\": textwrap.dedent(\"\"\"\n",
    "                This function multiplies two signals together with\n",
    "                an optional scale and offset.\n",
    "            \"\"\").strip(),\n",
    "            \"Formula\": \"($scale * addOnCalculation(@@scriptId@@, 'NUMERIC', $signal1, $signal2)) + $offset\",\n",
    "            \n",
    "            # List of parameters. Each dictionary corresponds to a parameter.\n",
    "            # There are four fields.\n",
    "            # Name (required) - the string name of the parameter\n",
    "            # Formula (optional) - the formula snippet that determines\n",
    "            #   the type and metadata of the parameter.\n",
    "            #   If the Formula is set, the DefaultValue must NOT be set.\n",
    "            # Optional (optional) - boolean, if this parameter is Optional.\n",
    "            #   If not set, the parameter is assumed to be required.\n",
    "            # DefaultValue (optional) - a default value to be used if none\n",
    "            # is provided.\n",
    "            #   Can only be set if Optional is true.\n",
    "            #   If set, the type of the parameter is determined by the type\n",
    "            #   of the default value provided. Do not use with Formula.\n",
    "    \n",
    "            # Parameters must be ordered as\n",
    "            # 1. Mandatory\n",
    "            # 2. Optional with default value\n",
    "            # 3. Optional without default value\n",
    "            #\n",
    "            # At least one parameter is required.\n",
    "            \"Parameters\": [\n",
    "                {'Name': 'signal1', 'Formula': 'sinusoid()'},\n",
    "                {'Name': 'signal2', 'Formula': 'sinusoid()'},\n",
    "                {'Name': 'scale', 'Optional': True, 'DefaultValue': '42'},\n",
    "                {'Name': 'offset', 'Optional': True, 'DefaultValue': '0'}\n",
    "            ],\n",
    "            \n",
    "            # List of examples. Each dictionary corresponds to an example.\n",
    "            # Each example must have a Formula.\n",
    "            # A Description is optional.\n",
    "    \n",
    "            # Different examples can describe different variants of the\n",
    "            # Add-on Function.\n",
    "            #\n",
    "            # @@functionName@@ is a placeholder and will be replaced automatically\n",
    "            # with packageName_functionName where packageName is defined by\n",
    "            # the folder this script is placed in and functionName is\n",
    "            # defined below in function_details.\n",
    "            \"Examples\": [\n",
    "                {\n",
    "                    'Formula': '@@functionName@@($seriesA, $seriesB, 2.5, 2)',\n",
    "                    'Description': 'Multiply $seriesA by $seriesB, scaled by 2.5 and add 2.'\n",
    "                },\n",
    "                {\n",
    "                    'Formula': '@@functionName@@($seriesA, $seriesB, 3)',\n",
    "                    'Description': 'Multiply $seriesA by $seriesB, scaled by 3.'\n",
    "                },\n",
    "                {\n",
    "                    'Formula': '@@functionName@@($seriesA, $seriesB)',\n",
    "                    'Description': 'Multiply $seriesA by $seriesB using the default scaling (42).'\n",
    "                }\n",
    "            ],\n",
    "        }\n",
    "    }\n",
    "\n",
    "    url = f\"{scheme}://{hostname}/data-lab/{project_id}/functions/notebooks/api/endpoints/compute-two-signals-multiply-with-offset\"\n",
    "    return url, metadata"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bb2c599-f345-4ab1-9c42-6673e149fd43",
   "metadata": {},
   "source": [
    "# Window Moving Average"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9be61bf9-1661-434a-ba53-5d2532261b7c",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def compute_window_moving_average(signal_data_types, signal_data, window_size):\n",
    "    def compute_for_window(keys: List[int], samples_for_keys: List[List]):\n",
    "        if None in samples_for_keys[0]:\n",
    "            return None\n",
    "        value = sum(samples_for_keys[0]) / len(keys)\n",
    "        return value\n",
    "    \n",
    "    number_of_samples = len(signal_data)\n",
    "    number_of_signals = len(signal_data[0]) - 1    \n",
    "    result_keys = []\n",
    "    result_values = []\n",
    "    for index in range(0, number_of_samples - window_size + 1):\n",
    "        window_data = signal_data[index:index + window_size]\n",
    "        keys = [k[0] for k in window_data]\n",
    "        values = [[k[s + 1] for k in window_data] for s in range(number_of_signals)]\n",
    "        result = compute_for_window(keys, values)\n",
    "        \n",
    "        if result is not None:\n",
    "            result_keys.append(signal_data[index][0])\n",
    "            result_values.append(result)\n",
    "    return result_keys, result_values\n",
    "\n",
    "def get_variables_window_moving_average():\n",
    "    metadata = {\n",
    "        # Type of input mode.\n",
    "        # either 'KEYWISE' or 'WINDOW'\n",
    "        \"inputMode\": \"WINDOW\",\n",
    "        \n",
    "        # Type of output signal.\n",
    "        # either 'NUMERIC' or 'STRING'\n",
    "        \"outputType\": \"NUMERIC\",\n",
    "        \n",
    "        # Dictionary of function details.\n",
    "        # Name (required): name of the function.\n",
    "        # Documentation (optional): documentation for the function.\n",
    "        # Formula (required): the Formula snippet that will be executed.\n",
    "        #   It must contain a call to\n",
    "        #   addOnCalculation or addOnCalculationOnWindow\n",
    "        #   with \"@@scriptId@@ as the first parameter.\n",
    "        #\n",
    "        #   Other Seeq operators can be used within the snippet. Other\n",
    "        #   parameters can be passed to the addOnCalculation or used by\n",
    "        #   Seeq operators in the complete formula.\n",
    "        # Parameters (required): described above.\n",
    "        # Examples (optional): described above.\n",
    "        #\n",
    "        # @@scriptId@@ is a placeholder and will be replaced with\n",
    "        # the correct identifier string automatically.\n",
    "        \"udfDefinition\": {\n",
    "            \"Name\": \"movingAverage\",\n",
    "            \"Documentation\": textwrap.dedent(\"\"\"\n",
    "                This function can compute the moving average\n",
    "                of any numeric signal using the power of add-on calculations.\n",
    "            \"\"\").strip(),\n",
    "            \"Formula\": \"addOnCalculationOnWindow(@@scriptId@@, 'NUMERIC', 1/hour, 1day, startKey(), $signal)\",\n",
    "            \n",
    "            # Parameters must be ordered as\n",
    "            # 1. Mandatory\n",
    "            # 2. Optional with default value\n",
    "            # 3. Optional without default value\n",
    "            #\n",
    "            # At least one parameter is required.\n",
    "            \"Parameters\": [\n",
    "                {'Name': 'signal', 'Formula': 'sinusoid()'},\n",
    "            ],\n",
    "            \n",
    "            # List of examples. Each dictionary corresponds to an example.\n",
    "            # Each example must have a Formula.\n",
    "            # A Description is optional.\n",
    "\n",
    "            # Different examples can describe different variants of the\n",
    "            # Add-on Function.\n",
    "            #\n",
    "            # @@functionName@@ is a placeholder and will be replaced automatically\n",
    "            # with packageName_functionName where packageName is defined by\n",
    "            # the folder this script is placed in and functionName is\n",
    "            # defined below in function_details.\n",
    "            \"Examples\": [\n",
    "                {\n",
    "                    'Formula': '$series.@@functionName@@()',\n",
    "                    'Description': 'Compute the moving average of $series'\n",
    "                }\n",
    "            ]\n",
    "        }\n",
    "    }\n",
    "\n",
    "    url = f\"{scheme}://{hostname}/data-lab/{project_id}/functions/notebooks/api/endpoints/compute-window-moving-average\"\n",
    "    return url, metadata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e45fa48f-2752-478a-9e0b-4bf9ba43688f",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# GET /not-used-but-not-context\n",
    "# Print the URLs for easy copying when creating a datasource\n",
    "keywise_numeric_negation_url, _ = get_variables_keywise_numeric_negation()\n",
    "keywise_two_signals_running_sum_url, _ = get_variables_keywise_two_signals_running_sum()\n",
    "keywise_two_signals_multiply_with_offset_url, _ = get_variables_keywise_two_signals_multiply_with_offset()\n",
    "window_moving_average_url, _ = get_variables_window_moving_average()\n",
    "print(f\"keywise numeric negation url: {keywise_numeric_negation_url}\")\n",
    "print(f\"keywise two signals running sum url: {keywise_two_signals_running_sum_url}\")\n",
    "print(f\"keywise two signals multiply with offset url: {keywise_two_signals_multiply_with_offset_url}\")\n",
    "print(f\"window moving average url: {window_moving_average_url}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21024dad-7fc8-4099-bc84-4fcee06d4d9f",
   "metadata": {},
   "source": [
    "# Keywise Numeric Negation Compute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6e631b75-12d9-42ee-ac51-be798f49065c",
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "# POST /compute-numeric-negation\n",
    "url, metadata = get_variables_keywise_numeric_negation()\n",
    "request_body = REQUEST.get('body')\n",
    "action = request_body.get('action')\n",
    "signal_data_types = request_body.get('signal_data_types')\n",
    "if action == \"metadata\":\n",
    "    output = metadata\n",
    "else:\n",
    "    signal_data = request_body.get('data')\n",
    "    result_keys, result_values = compute_keywise_numeric_negation(signal_data_types, signal_data)\n",
    "    result = {\n",
    "        \"doubleSignal\": result_values,\n",
    "        \"signalKeys\": result_keys,\n",
    "        \"outputType\": \"NUMERIC\"\n",
    "    }\n",
    "    output = {\n",
    "        # Supplying this content type prevents DL from serializing the response to JSON, which we do because it's faster to serialize here than to have DL serialize it.\n",
    "        'headers': {'Content-Type': 'application/vnd.seeq.v1+json'},\n",
    "        'data': json.dumps(result)\n",
    "    }\n",
    "output"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "08a556b5-b62a-4f5e-818d-8ac5f604ac7f",
   "metadata": {},
   "source": [
    "### Test Keywise Numeric Negation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c50820ef-2462-473c-b8b4-39bdcf4aacde",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# GET /self-check-compute-keywise-numeric-negation\n",
    "import requests\n",
    "\n",
    "url, _ = get_variables_keywise_numeric_negation()\n",
    "\n",
    "print(url)\n",
    "\n",
    "response = requests.post(\n",
    "    url=url,\n",
    "    headers={'x-sq-auth': spy.session.client.auth_token, 'Content-Type': 'application/json'},\n",
    "    data='{\"action\": \"compute\", \"signal_data_types\":[\"NUMERIC\"],\"data\":[[1712588760000000000,64.79883458],[1712588880000000000,64.7721975],[1712589000000000000,64.72177312],[1712589120000000000,64.69965861],[1712589240000000000,64.70305078],[1712589360000000000,64.73105014],[1712589480000000000,64.70893117],[1712589600000000000,64.73004111],[1712589720000000000,64.74612546],[1712589840000000000,64.69703431],[1712589960000000000,64.64668435],[1712590080000000000,64.59855146],[1712590200000000000,64.49149109],[1712590320000000000,64.44096772],[1712590440000000000,64.3989057],[1712590560000000000,64.33078],[1712590680000000000,64.28968941],[1712590800000000000,64.25166756],[1712590920000000000,64.27761228],[1712591040000000000,64.29980883],[1712600640000000000,64.46625369]]}'                \n",
    ")\n",
    "response.text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c52b4956-d8fa-479b-9123-fcc3b927e52a",
   "metadata": {
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# GET /self-check-metadata-keywise-numeric-negation\n",
    "import requests\n",
    "\n",
    "url, _ = get_variables_keywise_numeric_negation()\n",
    "\n",
    "response = requests.post(\n",
    "    url=url,\n",
    "    headers={'x-sq-auth': spy.session.client.auth_token, 'Content-Type': 'application/json'},\n",
    "    data='{\"action\": \"metadata\"}'                \n",
    ")\n",
    "response.text"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5d262a4b-53a1-463b-8134-2320bb34e86b",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Keywise Two Signals Running Sum Compute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9c653c4-50ac-4c54-980a-a58fd41b4572",
   "metadata": {},
   "outputs": [],
   "source": [
    "# POST /compute-two-signals-running-sum\n",
    "url, metadata = get_variables_keywise_two_signals_running_sum()\n",
    "request_body = REQUEST.get('body')\n",
    "action = request_body.get('action')\n",
    "signal_data_types = request_body.get('signal_data_types')\n",
    "if action == \"metadata\":\n",
    "    output = metadata\n",
    "else:\n",
    "    signal_data = request_body.get('data')\n",
    "    result_keys, result_values = compute_keywise_two_signals_running_sum(signal_data_types, signal_data)\n",
    "    result = {\n",
    "        \"doubleSignal\": result_values,\n",
    "        \"signalKeys\": result_keys,\n",
    "        \"outputType\": \"NUMERIC\"\n",
    "    }\n",
    "    output = {\n",
    "        # Supplying this content type prevents DL from serializing the response to JSON, which we do because it's faster to serialize here than to have DL serialize it.\n",
    "        'headers': {'Content-Type': 'application/vnd.seeq.v1+json'},\n",
    "        'data': json.dumps(result)\n",
    "    }\n",
    "output"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3afabe73-5c52-41b1-bba6-d0af0602c295",
   "metadata": {},
   "source": [
    "## Test Keywise Two Signals Running Sum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "041a382c-f7f4-46d7-87f5-4daad54f10f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# GET /self-check-compute-two-signals-running-sum\n",
    "import requests\n",
    "\n",
    "url, _ = get_variables_keywise_two_signals_running_sum()\n",
    "\n",
    "print(url)\n",
    "\n",
    "response = requests.post(\n",
    "    url=url,\n",
    "    headers={'x-sq-auth': spy.session.client.auth_token, 'Content-Type': 'application/json'},\n",
    "    data='{\"action\": \"compute\", \"signal_data_types\":[\"NUMERIC\"],\"data\":[[1712588760000000000,64.79883458,64.79883458],[1712588880000000000,64.7721975,64.7721975],[1712589000000000000,64.72177312,64.72177312],[1712589120000000000,64.69965861,64.69965861],[1712589240000000000,64.70305078,64.70305078],[1712589360000000000,64.73105014,64.73105014],[1712589480000000000,64.70893117,64.70893117],[1712589600000000000,64.73004111,64.73004111],[1712589720000000000,64.74612546,64.74612546],[1712589840000000000,64.69703431,64.69703431],[1712589960000000000,64.64668435,64.64668435],[1712590080000000000,64.59855146,64.59855146],[1712590200000000000,64.49149109,64.49149109],[1712590320000000000,64.44096772,64.44096772],[1712590440000000000,64.3989057,64.3989057],[1712590560000000000,64.33078,64.33078],[1712590680000000000,64.28968941,64.28968941],[1712590800000000000,64.25166756,64.25166756],[1712590920000000000,64.27761228,64.27761228],[1712591040000000000,64.29980883,64.29980883],[1712600640000000000,64.46625369,64.46625369]]}'                \n",
    ")\n",
    "response.text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f24b953-80b2-4834-81f6-7b72eca28e53",
   "metadata": {},
   "outputs": [],
   "source": [
    "# GET /self-check-metadata-two-signals-running-sum\n",
    "import requests\n",
    "\n",
    "url, _ = get_variables_keywise_two_signals_running_sum()\n",
    "\n",
    "response = requests.post(\n",
    "    url=url,\n",
    "    headers={'x-sq-auth': spy.session.client.auth_token, 'Content-Type': 'application/json'},\n",
    "    data='{\"action\": \"metadata\"}'                \n",
    ")\n",
    "response.text"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "303b4bf6-6ccf-4109-88a0-fe99c2d0c18c",
   "metadata": {},
   "source": [
    "# Keywise Two Signals Multiply With Offset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e2cc7fa-44a7-469e-beb1-832d5cecd01b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# POST /compute-two-signals-multiply-with-offset\n",
    "url, metadata = get_variables_keywise_two_signals_multiply_with_offset()\n",
    "request_body = REQUEST.get('body')\n",
    "action = request_body.get('action')\n",
    "signal_data_types = request_body.get('signal_data_types')\n",
    "if action == \"metadata\":\n",
    "    output = metadata\n",
    "else:\n",
    "    signal_data = request_body.get('data')\n",
    "    result_keys, result_values = compute_two_signals_multiply_with_offset(signal_data_types, signal_data)\n",
    "    result = {\n",
    "        \"doubleSignal\": result_values,\n",
    "        \"signalKeys\": result_keys,\n",
    "        \"outputType\": \"NUMERIC\"\n",
    "    }\n",
    "    output = {\n",
    "        # Supplying this content type prevents DL from serializing the response to JSON, which we do because it's faster to serialize here than to have DL serialize it.\n",
    "        'headers': {'Content-Type': 'application/vnd.seeq.v1+json'},\n",
    "        'data': json.dumps(result)\n",
    "    }\n",
    "output"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "111d64a7-e76e-4b6b-a438-2564331b1e92",
   "metadata": {},
   "source": [
    "## Test Keywise Two Signals Multiply With Offset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b08b11a-f061-4c05-ab60-12c0a94df045",
   "metadata": {},
   "outputs": [],
   "source": [
    "# GET /self-check-compute-two-signals-multiply-with-offset\n",
    "import requests\n",
    "\n",
    "url, _ = get_variables_keywise_two_signals_multiply_with_offset()\n",
    "\n",
    "print(url)\n",
    "\n",
    "response = requests.post(\n",
    "    url=url,\n",
    "    headers={'x-sq-auth': spy.session.client.auth_token, 'Content-Type': 'application/json'},\n",
    "    data='{\"action\": \"compute\", \"signal_data_types\":[\"NUMERIC\"],\"data\":[[1712588760000000000,64.79883458,64.79883458],[1712588880000000000,64.7721975,64.7721975],[1712589000000000000,64.72177312,64.72177312],[1712589120000000000,64.69965861,64.69965861],[1712589240000000000,64.70305078,64.70305078],[1712589360000000000,64.73105014,64.73105014],[1712589480000000000,64.70893117,64.70893117],[1712589600000000000,64.73004111,64.73004111],[1712589720000000000,64.74612546,64.74612546],[1712589840000000000,64.69703431,64.69703431],[1712589960000000000,64.64668435,64.64668435],[1712590080000000000,64.59855146,64.59855146],[1712590200000000000,64.49149109,64.49149109],[1712590320000000000,64.44096772,64.44096772],[1712590440000000000,64.3989057,64.3989057],[1712590560000000000,64.33078,64.33078],[1712590680000000000,64.28968941,64.28968941],[1712590800000000000,64.25166756,64.25166756],[1712590920000000000,64.27761228,64.27761228],[1712591040000000000,64.29980883,64.29980883],[1712600640000000000,64.46625369,64.46625369]]}'                \n",
    ")\n",
    "response.text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "173cd9ca-043f-4667-b254-819eb72751e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# GET /self-check-metadata-two-signals-multiply-with-offset\n",
    "import requests\n",
    "\n",
    "url, _ = get_variables_keywise_two_signals_multiply_with_offset()\n",
    "\n",
    "response = requests.post(\n",
    "    url=url,\n",
    "    headers={'x-sq-auth': spy.session.client.auth_token, 'Content-Type': 'application/json'},\n",
    "    data='{\"action\": \"metadata\"}'                \n",
    ")\n",
    "response.text"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3fded106-504b-4d3e-a991-4d08920b9645",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Window Moving Average Compute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75d41243-c6f3-48fd-8591-bc3e8cc24265",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# POST /compute-window-moving-average\n",
    "url, metadata = get_variables_window_moving_average()\n",
    "request_body = REQUEST.get('body')\n",
    "action = request_body.get('action')\n",
    "signal_data_types = request_body.get('signal_data_types')\n",
    "if action == \"metadata\":\n",
    "    print(metadata)\n",
    "else:\n",
    "    signal_data = request_body.get('data')\n",
    "    window_size = request_body.get('window_size')\n",
    "    result_keys, result_values = compute_window_moving_average(signal_data_types, signal_data, window_size)\n",
    "    result = {\n",
    "        \"doubleSignal\": result_values,\n",
    "        \"signalKeys\": result_keys,\n",
    "        \"outputType\": \"NUMERIC\"\n",
    "    }\n",
    "    print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a3e8e027-612b-4e45-a0c0-bc5702be333c",
   "metadata": {},
   "source": [
    "### Test Window"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7cfa21f0-301c-485a-ba28-fbde83732120",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# GET /self-check-compute-window-moving-average\n",
    "import requests\n",
    "\n",
    "url, _ = get_variables_window_moving_average()\n",
    "\n",
    "response = requests.post(\n",
    "    url=url,\n",
    "    headers={'x-sq-auth': spy.session.client.auth_token, 'Content-Type': 'application/json'},\n",
    "    data='{\"action\":\"compute\",\"signal_data_types\":[\"NUMERIC\"],\"data\":[[1715457600000000000,82.43574576],[1715461200000000000,87.63449123],[1715464800000000000,91.39998361],[1715468400000000000,94.04006897],[1715472000000000000,98.52216529],[1715475600000000000,103.7446281],[1715479200000000000,103.4786066],[1715482800000000000,103.5463248],[1715486400000000000,102.0174359],[1715490000000000000,98.30390164],[1715493600000000000,91.12817424],[1715497200000000000,88.19386066],[1715500800000000000,85.1921405],[1715504400000000000,82.58028],[1715508000000000000,81.29359649],[1715511600000000000,79.80759664],[1715515200000000000,78.20989158],[1715518800000000000,76.04077686],[1715522400000000000,75.20440678],[1715526000000000000,73.930984],[1715529600000000000,73.80752137],[1715533200000000000,73.30133333],[1715536800000000000,72.24554074],[1715540400000000000,78.55426496],[1715544000000000000,81.31013793],[1715547600000000000,87.08476],[1715551200000000000,null],[1715554800000000000,null],[1715558400000000000,null],[1715562000000000000,null],[1715565600000000000,null],[1715569200000000000,null],[1715572800000000000,null],[1715576400000000000,null],[1715580000000000000,null],[1715583600000000000,null],[1715587200000000000,null],[1715590800000000000,null],[1715594400000000000,null],[1715598000000000000,null],[1715601600000000000,null],[1715605200000000000,null],[1715608800000000000,null],[1715612400000000000,null],[1715616000000000000,null],[1715619600000000000,null],[1715623200000000000,null],[1715626800000000000,null],[1715630400000000000,null],[1715634000000000000,null],[1715637600000000000,null],[1715641200000000000,null]],\"window_size\":24}'\n",
    ")\n",
    "response.text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d518899-d687-45a9-b691-0a3476c0c66b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# GET /self-check-metadata-window-moving-average\n",
    "import requests\n",
    "\n",
    "url, _ = get_variables_window_moving_average()\n",
    "\n",
    "response = requests.post(\n",
    "    url=url,\n",
    "    headers={'x-sq-auth': spy.session.client.auth_token, 'Content-Type': 'application/json'},\n",
    "    data='{\"action\": \"metadata\"}'                \n",
    ")\n",
    "response.text"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.11",
   "language": "python",
   "name": "python311"
  },
  "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.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
