sysstra 0.1.2__tar.gz → 0.1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sysstra-0.1.2 → sysstra-0.1.2.0}/PKG-INFO +8 -3
- {sysstra-0.1.2 → sysstra-0.1.2.0}/setup.py +8 -6
- sysstra-0.1.2.0/sysstra/__init__.py +23 -0
- {sysstra-0.1.2/src → sysstra-0.1.2.0/sysstra}/custom_indicators.py +3 -3
- {sysstra-0.1.2/src → sysstra-0.1.2.0/sysstra}/data/historical.py +41 -15
- sysstra-0.1.2.0/sysstra/orders/backtest.py +57 -0
- sysstra-0.1.2.0/sysstra/orders/common.py +196 -0
- sysstra-0.1.2.0/sysstra/orders/live.py +186 -0
- sysstra-0.1.2.0/sysstra/orders/virtual.py +104 -0
- {sysstra-0.1.2/src → sysstra-0.1.2.0/sysstra}/utils.py +200 -5
- {sysstra-0.1.2 → sysstra-0.1.2.0}/sysstra.egg-info/PKG-INFO +8 -3
- sysstra-0.1.2.0/sysstra.egg-info/SOURCES.txt +18 -0
- {sysstra-0.1.2 → sysstra-0.1.2.0}/sysstra.egg-info/requires.txt +1 -0
- sysstra-0.1.2.0/sysstra.egg-info/top_level.txt +1 -0
- sysstra-0.1.2/src/__init__.py +0 -7
- sysstra-0.1.2/src/data/__init__.py +0 -2
- sysstra-0.1.2/src/orders/kite.py +0 -36
- sysstra-0.1.2/src/orders/orders.py +0 -489
- sysstra-0.1.2/sysstra.egg-info/SOURCES.txt +0 -17
- sysstra-0.1.2/sysstra.egg-info/top_level.txt +0 -1
- {sysstra-0.1.2 → sysstra-0.1.2.0}/LICENSE +0 -0
- {sysstra-0.1.2 → sysstra-0.1.2.0}/README.md +0 -0
- {sysstra-0.1.2 → sysstra-0.1.2.0}/setup.cfg +0 -0
- {sysstra-0.1.2/src → sysstra-0.1.2.0/sysstra}/data/live.py +0 -0
- {sysstra-0.1.2/src → sysstra-0.1.2.0/sysstra}/orders/__init__.py +0 -0
- {sysstra-0.1.2 → sysstra-0.1.2.0}/sysstra.egg-info/dependency_links.txt +0 -0
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sysstra
|
|
3
|
-
Version: 0.1.2
|
|
3
|
+
Version: 0.1.2.0
|
|
4
4
|
Summary: Official Python Library for Sysstra Algo Trading
|
|
5
5
|
Home-page: https://github.com/sysstra/sysstra
|
|
6
6
|
Author: Anurag Singh Kushwah
|
|
7
|
-
Author-email:
|
|
7
|
+
Author-email: anurag@techrefic.com
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
+
Requires-Dist: requests
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Requires-Dist: pandas_ta
|
|
17
|
+
Requires-Dist: redis
|
|
18
|
+
Requires-Dist: pandas
|
|
14
19
|
|
|
15
20
|
## Hi there 👋
|
|
16
21
|
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
from setuptools import setup, find_packages
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
|
-
name="sysstra",
|
|
5
|
-
version="0.1.2",
|
|
4
|
+
name="sysstra",
|
|
5
|
+
version="0.1.2.0",
|
|
6
6
|
description="Official Python Library for Sysstra Algo Trading",
|
|
7
7
|
long_description=open("README.md").read(),
|
|
8
8
|
long_description_content_type="text/markdown",
|
|
9
9
|
author="Anurag Singh Kushwah",
|
|
10
|
-
author_email="
|
|
11
|
-
url="https://github.com/sysstra/sysstra",
|
|
12
|
-
packages=find_packages(),
|
|
10
|
+
author_email="anurag@techrefic.com",
|
|
11
|
+
url="https://github.com/sysstra/sysstra",
|
|
12
|
+
packages=find_packages(),
|
|
13
|
+
include_package_data=True,
|
|
13
14
|
install_requires=[ # Dependencies
|
|
14
15
|
"requests",
|
|
15
16
|
"numpy",
|
|
16
17
|
"pandas_ta",
|
|
17
18
|
"redis",
|
|
19
|
+
"pandas"
|
|
18
20
|
],
|
|
19
21
|
classifiers=[ # Additional metadata (check PyPI classifiers)
|
|
20
22
|
"Programming Language :: Python :: 3",
|
|
21
23
|
"License :: OSI Approved :: MIT License",
|
|
22
24
|
"Operating System :: OS Independent",
|
|
23
25
|
],
|
|
24
|
-
python_requires=">=3.
|
|
26
|
+
python_requires=">=3.9",
|
|
25
27
|
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
api_key: str | None = None
|
|
2
|
+
# data_url: str | None = None
|
|
3
|
+
orders_url: str | None = None
|
|
4
|
+
|
|
5
|
+
data_url = "https://api.data.sysstra.com/"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def set_api_key(key):
|
|
9
|
+
""" Function to set api key """
|
|
10
|
+
global api_key
|
|
11
|
+
api_key = key
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def set_data_url(url):
|
|
15
|
+
""" Function to set data url """
|
|
16
|
+
global data_url
|
|
17
|
+
data_url = url
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def set_orders_url(url):
|
|
21
|
+
""" Function to set Orders URL """
|
|
22
|
+
global orders_url
|
|
23
|
+
orders_url = url
|
|
@@ -459,7 +459,7 @@ def jurik_moving_average(dataframe, length=20, phase=50, power=2, source='close'
|
|
|
459
459
|
try:
|
|
460
460
|
df = dataframe.copy()
|
|
461
461
|
# Initialize necessary columns and constants
|
|
462
|
-
df['
|
|
462
|
+
df['sysstra'] = df[source] # By default, using 'close' as the source
|
|
463
463
|
phase_ratio = np.where(phase < -100, 0.5, np.where(phase > 100, 2.5, phase / 100 + 1.5))
|
|
464
464
|
|
|
465
465
|
beta = 0.45 * (length - 1) / (0.45 * (length - 1) + 2)
|
|
@@ -473,8 +473,8 @@ def jurik_moving_average(dataframe, length=20, phase=50, power=2, source='close'
|
|
|
473
473
|
|
|
474
474
|
# Calculate JMA
|
|
475
475
|
for i in range(1, len(df)):
|
|
476
|
-
df.at[i, 'e0'] = (1 - alpha) * df.at[i, '
|
|
477
|
-
df.at[i, 'e1'] = (df.at[i, '
|
|
476
|
+
df.at[i, 'e0'] = (1 - alpha) * df.at[i, 'sysstra'] + alpha * df.at[i - 1, 'e0']
|
|
477
|
+
df.at[i, 'e1'] = (df.at[i, 'sysstra'] - df.at[i, 'e0']) * (1 - beta) + beta * df.at[i - 1, 'e1']
|
|
478
478
|
df.at[i, 'e2'] = (df.at[i, 'e0'] + phase_ratio * df.at[i, 'e1'] - df.at[i - 1, 'jma']) * (1 - alpha) ** 2 + (alpha ** 2) * df.at[i - 1, 'e2']
|
|
479
479
|
df.at[i, 'jma'] = df.at[i, 'e2'] + df.at[i - 1, 'jma']
|
|
480
480
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import requests
|
|
2
|
-
from
|
|
3
|
+
from sysstra import api_key, data_url
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
def fetch_eod_candles(exchange, symbol, start_date, end_date):
|
|
@@ -9,7 +10,7 @@ def fetch_eod_candles(exchange, symbol, start_date, end_date):
|
|
|
9
10
|
request_data = {"exchange": exchange, "symbol": symbol, "from_date": start_date, "to_date": end_date}
|
|
10
11
|
request_url = f"{data_url}/fetch-eod-data"
|
|
11
12
|
eod_data = requests.post(url=request_url, headers=headers, json=request_data)
|
|
12
|
-
return eod_data
|
|
13
|
+
return eod_data.json()
|
|
13
14
|
except Exception as e:
|
|
14
15
|
print(f"Exception in fetching eod candles : {e}")
|
|
15
16
|
return []
|
|
@@ -23,7 +24,7 @@ def fetch_index_candles(exchange, symbol, start_date, end_date, granularity=1):
|
|
|
23
24
|
"granularity": granularity}
|
|
24
25
|
request_url = f"{data_url}/fetch-index-data"
|
|
25
26
|
candles_data = requests.post(url=request_url, headers=headers, json=request_data)
|
|
26
|
-
return candles_data
|
|
27
|
+
return candles_data.json()
|
|
27
28
|
except Exception as e:
|
|
28
29
|
print(f"Exception in fetching date candles : {e}")
|
|
29
30
|
return []
|
|
@@ -38,7 +39,7 @@ def fetch_option_candles(exchange, underlying_symbol, start_date, end_date, opti
|
|
|
38
39
|
"expiry": expiry, "granularity": granularity}
|
|
39
40
|
request_url = f"{data_url}/fetch-options-data"
|
|
40
41
|
candles_data = requests.post(url=request_url, headers=headers, json=request_data)
|
|
41
|
-
return candles_data
|
|
42
|
+
return candles_data.json()
|
|
42
43
|
except Exception as e:
|
|
43
44
|
print(f"Exception in fetching options candle : {e}")
|
|
44
45
|
return []
|
|
@@ -51,35 +52,60 @@ def fetch_option_candles_by_symbol(exchange, symbol, start_date, end_date, granu
|
|
|
51
52
|
request_data = {"exchange": exchange, "symbol": symbol, "from_date": start_date, "to_date": end_date, "granularity": granularity}
|
|
52
53
|
request_url = f"{data_url}/fetch-options-data-by-symbol"
|
|
53
54
|
candles_data = requests.post(url=request_url, headers=headers, json=request_data)
|
|
54
|
-
return candles_data
|
|
55
|
+
return candles_data.json()
|
|
55
56
|
|
|
56
57
|
except Exception as e:
|
|
57
58
|
print(f"Exception in fetching options candle : {e}")
|
|
58
59
|
return []
|
|
59
60
|
|
|
60
61
|
|
|
61
|
-
def fetch_option_candle_by_timestamp(exchange, underlying_symbol, strike_price, option_type, timestamp, expiry="near"):
|
|
62
|
+
def fetch_option_candle_by_timestamp(exchange, underlying_symbol, strike_price, option_type, timestamp, granularity=1, expiry="near"):
|
|
62
63
|
""" Function to Fetch Order Candle based on timestamp """
|
|
63
64
|
try:
|
|
64
65
|
headers = {"x-api-key": api_key, "content-type": "application/json"}
|
|
65
66
|
request_data = {"exchange": exchange, "underlying_symbol": underlying_symbol, "option_type": option_type,
|
|
66
|
-
"strike_price": strike_price, "timestamp": timestamp, "expiry": expiry}
|
|
67
|
+
"strike_price": strike_price, "timestamp": str(timestamp), "expiry": expiry, "granularity": granularity}
|
|
67
68
|
request_url = f"{data_url}/fetch-option-data-by-timestamp"
|
|
68
69
|
candles_data = requests.post(url=request_url, headers=headers, json=request_data)
|
|
69
|
-
return candles_data
|
|
70
|
+
return candles_data.json()
|
|
70
71
|
|
|
71
72
|
except Exception as e:
|
|
72
73
|
print(f"Exception in fetching order candle : {e}")
|
|
73
74
|
return []
|
|
74
75
|
|
|
75
76
|
|
|
77
|
+
def fetch_crypto_candles(exchange, symbol, start_date, end_date, granularity=1):
|
|
78
|
+
""" Function to fetch candles for the respective date """
|
|
79
|
+
try:
|
|
80
|
+
headers = {"x-api-key": api_key, "content-type": "application/json"}
|
|
81
|
+
request_data = {"exchange": exchange, "symbol": symbol, "from_date": start_date, "to_date": end_date,
|
|
82
|
+
"granularity": granularity}
|
|
83
|
+
request_url = f"{data_url}/fetch-crypto-data"
|
|
84
|
+
candles_data = requests.post(url=request_url, headers=headers, json=request_data)
|
|
85
|
+
return candles_data.json()
|
|
86
|
+
except Exception as e:
|
|
87
|
+
print(f"Exception in fetching crypto candles : {e}")
|
|
88
|
+
return []
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def fetch_forex_candles(exchange, symbol, start_date, end_date, granularity=1):
|
|
92
|
+
""" Function to fetch candles for the respective date """
|
|
93
|
+
try:
|
|
94
|
+
headers = {"x-api-key": api_key, "content-type": "application/json"}
|
|
95
|
+
request_data = {"exchange": exchange, "symbol": symbol, "from_date": start_date, "to_date": end_date,
|
|
96
|
+
"granularity": granularity}
|
|
97
|
+
request_url = f"{data_url}/fetch-forex-data"
|
|
98
|
+
candles_data = requests.post(url=request_url, headers=headers, json=request_data)
|
|
99
|
+
return candles_data.json()
|
|
100
|
+
except Exception as e:
|
|
101
|
+
print(f"Exception in fetching forex candles : {e}")
|
|
102
|
+
return []
|
|
103
|
+
|
|
104
|
+
|
|
76
105
|
if __name__ == '__main__':
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
# candles = fetch_option_candles(exchange="NSE", underlying_symbol="SENSEX", start_date="19/12/2024",
|
|
80
|
-
# end_date="19/12/2024", strike_price=80200, option_type="CE", expiry="near")
|
|
81
|
-
# candles = fetch_option_candles_by_symbol(exchange="NSE", symbol="SENSEX24D2080200CE", start_date="19/12/2024",
|
|
82
|
-
# end_date="19/12/2024")
|
|
106
|
+
api_key = "123asdf"
|
|
107
|
+
data_url = "http://127.0.0.1:5001"
|
|
83
108
|
candle = fetch_option_candle_by_timestamp(exchange="NSE", underlying_symbol="SENSEX", strike_price=80200, option_type="CE", expiry="near",
|
|
84
109
|
timestamp="2024-12-19 14:45:00")
|
|
85
|
-
print(candle)
|
|
110
|
+
print(json.loads(candle.content))
|
|
111
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from sysstra.orders.common import fetch_orders_list, add_order_to_redis
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def save_bt_report(app_db_cursor, report_dict):
|
|
5
|
+
"""Function to Save Backtest Report in Database"""
|
|
6
|
+
try:
|
|
7
|
+
app_db_cursor["bt_reports"].insert_one(report_dict)
|
|
8
|
+
app_db_cursor["bt_request"].update_one({"_id": report_dict["request_id"]}, {"$set": {"status": "done"}})
|
|
9
|
+
except Exception as e:
|
|
10
|
+
print(f"Exception in saving BT Report : {e}")
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def place_bt_order(rdb_cursor, order_candle, position_type, quantity, transaction_type, order_type, orders_list, option_type=None, strike_price=None, exit_type=None, quantity_left=0, params=None, market_type="cash", trade_type=None, trigger_price=None, lot_size=25, user_id=None, strategy_id=None, request_id=None, exchange="NSE", option_params=None):
|
|
15
|
+
""" Function to place Backtesting Order """
|
|
16
|
+
try:
|
|
17
|
+
|
|
18
|
+
print("************** Placing Backtesting Order **************")
|
|
19
|
+
order_dict = {"exchange": "NSE", "order_type": order_type, "position_type": position_type, "quantity": quantity,
|
|
20
|
+
"transaction_type": transaction_type, "exit_type": exit_type, "quantity_left": quantity_left,
|
|
21
|
+
"lot_size": lot_size, "trade_type": trade_type}
|
|
22
|
+
|
|
23
|
+
if trigger_price:
|
|
24
|
+
order_dict["trigger_price"] = trigger_price
|
|
25
|
+
else:
|
|
26
|
+
order_dict["trigger_price"] = order_candle["close"]
|
|
27
|
+
|
|
28
|
+
order_dict["order_timestamp"] = str(order_candle["timestamp"])
|
|
29
|
+
order_dict["tradingsymbol"] = order_candle["symbol"]
|
|
30
|
+
order_dict["date"] = str(order_candle["date"])
|
|
31
|
+
|
|
32
|
+
if market_type == "options":
|
|
33
|
+
order_dict["expiry"] = order_candle["expiry"]
|
|
34
|
+
order_dict["option_type"] = option_type
|
|
35
|
+
order_dict["strike_price"] = strike_price
|
|
36
|
+
else:
|
|
37
|
+
order_dict["expiry"] = ""
|
|
38
|
+
order_dict["option_type"] = ""
|
|
39
|
+
order_dict["strike_price"] = ""
|
|
40
|
+
|
|
41
|
+
order_dict["day"] = order_candle["date"].strftime("%A")
|
|
42
|
+
|
|
43
|
+
if params:
|
|
44
|
+
order_dict.update(params)
|
|
45
|
+
|
|
46
|
+
if option_params:
|
|
47
|
+
order_dict.update(option_params)
|
|
48
|
+
|
|
49
|
+
print(f"***** bt_order : {order_dict}")
|
|
50
|
+
orders_list.append(order_dict)
|
|
51
|
+
|
|
52
|
+
return orders_list
|
|
53
|
+
|
|
54
|
+
except Exception as e:
|
|
55
|
+
print(f"Exception in placing backtesting order : {e}")
|
|
56
|
+
pass
|
|
57
|
+
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import datetime
|
|
3
|
+
from bson import ObjectId
|
|
4
|
+
from sysstra.utils import calculate_brokerage
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def add_order_to_redis(rdb_cursor, request_id, order_dict, mode):
|
|
8
|
+
"""Function to add order to redis"""
|
|
9
|
+
try:
|
|
10
|
+
rdb_cursor.rpush(str(request_id) + "_orders", json.dumps(order_dict, default=str))
|
|
11
|
+
rdb_cursor.publish(str(request_id) + "_orders", json.dumps(order_dict, default=str))
|
|
12
|
+
rdb_cursor.publish(str(order_dict["user_id"]) + "_{}".format(mode) + "_orders", json.dumps(order_dict, default=str))
|
|
13
|
+
except Exception as e:
|
|
14
|
+
print(f"Exception in adding order in redis : {e}")
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def fetch_orders_list(rdb_cursor, request_id):
|
|
19
|
+
""" Function to fetch an orders list for request_id """
|
|
20
|
+
try:
|
|
21
|
+
orders_list_json = rdb_cursor.lrange(str(request_id)+"_orders", 0, -1)
|
|
22
|
+
orders_list = [json.loads(i) for i in orders_list_json]
|
|
23
|
+
return orders_list
|
|
24
|
+
except Exception as e:
|
|
25
|
+
print(f"Exception in fetching orders list : {e}")
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def fetch_last_order(rdb_cursor, request_id):
|
|
30
|
+
"""Function to fetch last order from redis database"""
|
|
31
|
+
try:
|
|
32
|
+
last_order = json.loads(rdb_cursor.lindex(str(request_id) + "_orders", -1))
|
|
33
|
+
return last_order
|
|
34
|
+
except Exception as e:
|
|
35
|
+
print(f"Exception in fetching last order : {e}")
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def check_open_orders(orders_list):
|
|
40
|
+
""" Function to open orders available """
|
|
41
|
+
try:
|
|
42
|
+
if orders_list:
|
|
43
|
+
quantity_dict = {}
|
|
44
|
+
for order in orders_list:
|
|
45
|
+
trade_symbol = order["tradingsymbol"]
|
|
46
|
+
quantity_dict[trade_symbol] = {}
|
|
47
|
+
quantity_dict[trade_symbol]["buy_quantity"] = 0
|
|
48
|
+
quantity_dict[trade_symbol]["sell_quantity"] = 0
|
|
49
|
+
quantity_dict[trade_symbol]["quantity"] = 0
|
|
50
|
+
quantity_dict[trade_symbol]["option_type"] = ""
|
|
51
|
+
quantity_dict[trade_symbol]["strike_price"] = ""
|
|
52
|
+
quantity_dict[trade_symbol]["exit_levels"] = []
|
|
53
|
+
quantity_dict[trade_symbol]["order_timestamp"] = ""
|
|
54
|
+
quantity_dict[trade_symbol]["quantity_left"] = 0
|
|
55
|
+
quantity_dict[trade_symbol]["bnf_price"] = 0
|
|
56
|
+
quantity_dict[trade_symbol]["expiry"] = ""
|
|
57
|
+
quantity_dict[trade_symbol]["sl_order_id"] = ""
|
|
58
|
+
quantity_dict[trade_symbol]["option_order_price"] = 0
|
|
59
|
+
quantity_dict[trade_symbol]["hka_option_order_price"] = 0
|
|
60
|
+
quantity_dict[trade_symbol]["trailing_sl"] = 0
|
|
61
|
+
|
|
62
|
+
for order in orders_list:
|
|
63
|
+
trade_symbol = order["tradingsymbol"]
|
|
64
|
+
if order["trade_type"] == "ENTRY":
|
|
65
|
+
quantity_dict[trade_symbol]["buy_quantity"] = order["quantity"]
|
|
66
|
+
quantity_dict[trade_symbol]["quantity"] = order["quantity"]
|
|
67
|
+
quantity_dict[trade_symbol]["option_type"] = order["option_type"]
|
|
68
|
+
quantity_dict[trade_symbol]["strike_price"] = order["strike_price"]
|
|
69
|
+
quantity_dict[trade_symbol]["trigger_price"] = order["trigger_price"]
|
|
70
|
+
quantity_dict[trade_symbol]["order_timestamp"] = datetime.datetime.strptime(str(order["order_timestamp"]), '%Y-%m-%d %H:%M:%S')
|
|
71
|
+
quantity_dict[trade_symbol]["quantity_left"] = order["quantity_left"]
|
|
72
|
+
quantity_dict[trade_symbol]["bnf_price"] = order["bnf_price"]
|
|
73
|
+
quantity_dict[trade_symbol]["hka_option_order_price"] = order["hka_option_order_price"]
|
|
74
|
+
quantity_dict[trade_symbol]["option_order_price"] = order["option_order_price"]
|
|
75
|
+
|
|
76
|
+
if "expiry" in order:
|
|
77
|
+
quantity_dict[trade_symbol]["expiry"] = order["expiry"]
|
|
78
|
+
|
|
79
|
+
if "sl_order_id" in order:
|
|
80
|
+
quantity_dict[trade_symbol]["sl_order_id"] = order["sl_order_id"]
|
|
81
|
+
|
|
82
|
+
if "trailing_sl" in order:
|
|
83
|
+
quantity_dict[trade_symbol]["trailing_sl"] = order["trailing_sl"]
|
|
84
|
+
|
|
85
|
+
elif order["trade_type"] == "EXIT":
|
|
86
|
+
quantity_dict[trade_symbol]["sell_quantity"] += order["quantity"]
|
|
87
|
+
quantity_dict[trade_symbol]["quantity_left"] = order["quantity_left"]
|
|
88
|
+
quantity_dict[trade_symbol]["exit_levels"].append(order["exit_type"])
|
|
89
|
+
|
|
90
|
+
final_out = {}
|
|
91
|
+
for entries in quantity_dict:
|
|
92
|
+
# if quantity_dict[entries]["buy_quantity"] - quantity_dict[entries]["sell_quantity"] > 0:
|
|
93
|
+
if quantity_dict[entries]["quantity_left"] > 0:
|
|
94
|
+
final_out[entries] = quantity_dict[entries]
|
|
95
|
+
return final_out
|
|
96
|
+
|
|
97
|
+
else:
|
|
98
|
+
return {}
|
|
99
|
+
except Exception as e:
|
|
100
|
+
print(f"Exception in checking open orders : {e}")
|
|
101
|
+
return {}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def convert_to_trades(orders_list, market_type, order_exit_levels, mode, broker):
|
|
105
|
+
"""Function to convert Orders to Trades """
|
|
106
|
+
try:
|
|
107
|
+
trade_dict = {}
|
|
108
|
+
trades_array = []
|
|
109
|
+
for order in orders_list:
|
|
110
|
+
if order["trade_type"] == "ENTRY":
|
|
111
|
+
trade_dict["date"] = order["date"]
|
|
112
|
+
trade_dict["stock"] = order["tradingsymbol"]
|
|
113
|
+
trade_dict["lot_size"] = order["lot_size"]
|
|
114
|
+
trade_dict["trade_type"] = order["trade_type"]
|
|
115
|
+
trade_dict["bnf_price"] = order["bnf_price"]
|
|
116
|
+
trade_dict["bar_color"] = order["bar_color"]
|
|
117
|
+
trade_dict["entry_time"] = order["order_timestamp"]
|
|
118
|
+
trade_dict["entry_price"] = order["trigger_price"]
|
|
119
|
+
trade_dict["quantity"] = order["quantity"]
|
|
120
|
+
trade_dict["pnl"] = 0
|
|
121
|
+
trade_dict["points"] = 0
|
|
122
|
+
trade_dict["exit_time"] = None
|
|
123
|
+
trade_dict["exit_price"] = None
|
|
124
|
+
trade_dict["exit_type"] = ""
|
|
125
|
+
trade_dict["day"] = order["day"]
|
|
126
|
+
trade_dict["expiry"] = order["expiry"]
|
|
127
|
+
trade_dict["brokerage"] = 0
|
|
128
|
+
trade_dict["net_pnl"] = 0
|
|
129
|
+
|
|
130
|
+
if mode == "lt" or mode == "vt":
|
|
131
|
+
trade_dict["date"] = datetime.datetime.strptime(str(datetime.datetime.today().date()), '%Y-%m-%d')
|
|
132
|
+
trade_dict["user_id"] = ObjectId(order["user_id"])
|
|
133
|
+
trade_dict["strategy_id"] = ObjectId(order["strategy_id"])
|
|
134
|
+
trade_dict["request_id"] = ObjectId(order["request_id"])
|
|
135
|
+
|
|
136
|
+
else:
|
|
137
|
+
if market_type == "cash":
|
|
138
|
+
if order["trade_type"] == "SHORT":
|
|
139
|
+
points = trade_dict["entry_price"] - order["trigger_price"]
|
|
140
|
+
trade_dict["points"] += round(points)
|
|
141
|
+
trade_dict["pnl"] += round(order["quantity"] * points)
|
|
142
|
+
else:
|
|
143
|
+
points = order["trigger_price"] - trade_dict["entry_price"]
|
|
144
|
+
trade_dict["points"] += round(points)
|
|
145
|
+
trade_dict["pnl"] += round(order["quantity"] * points)
|
|
146
|
+
# trade_dict["pnl"] += round(order["quantity"] * trade_dict["points"])
|
|
147
|
+
else:
|
|
148
|
+
points = order["trigger_price"] - trade_dict["entry_price"]
|
|
149
|
+
trade_dict["points"] += round(points)
|
|
150
|
+
trade_dict["pnl"] += round(order["quantity"] * trade_dict["points"] * trade_dict["lot_size"])
|
|
151
|
+
|
|
152
|
+
if trade_dict["exit_type"]:
|
|
153
|
+
trade_dict["exit_type"] += "|" + order["exit_type"]
|
|
154
|
+
else:
|
|
155
|
+
trade_dict["exit_type"] = order["exit_type"]
|
|
156
|
+
|
|
157
|
+
if order["exit_type"] in order_exit_levels:
|
|
158
|
+
trade_dict["exit_time"] = order["order_timestamp"]
|
|
159
|
+
trade_dict["exit_price"] = order["trigger_price"]
|
|
160
|
+
|
|
161
|
+
brokerage, net_pnl = calculate_brokerage(buy_price=trade_dict["entry_price"], sell_price=trade_dict["exit_price"],
|
|
162
|
+
quantity=order["quantity"] * trade_dict["lot_size"], broker=broker)
|
|
163
|
+
trade_dict["brokerage"] += brokerage
|
|
164
|
+
trade_dict["net_pnl"] += net_pnl
|
|
165
|
+
|
|
166
|
+
trades_array.append(trade_dict)
|
|
167
|
+
|
|
168
|
+
# Emptying Trade Dict for next trade
|
|
169
|
+
trade_dict = {}
|
|
170
|
+
else:
|
|
171
|
+
brokerage, net_pnl = calculate_brokerage(buy_price=trade_dict["entry_price"], sell_price=order["trigger_price"],
|
|
172
|
+
quantity=order["quantity"] * trade_dict["lot_size"], broker=broker)
|
|
173
|
+
trade_dict["brokerage"] += brokerage
|
|
174
|
+
trade_dict["net_pnl"] += net_pnl
|
|
175
|
+
return trades_array
|
|
176
|
+
except Exception as e:
|
|
177
|
+
print(f"Exception in converting orders to trades : {e}")
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def check_existing_order(strike_price, option_type, position_type, order_type, orders_list, entry_time=None):
|
|
182
|
+
"""Function to check existing order on defined symbol"""
|
|
183
|
+
try:
|
|
184
|
+
for order in orders_list:
|
|
185
|
+
# if order["tradingsymbol"] == symbol and order["position_type"] == position_type and order["exit_type"] == order_type :
|
|
186
|
+
if not entry_time:
|
|
187
|
+
if order["strike_price"] == strike_price and order["option_type"] == option_type and order["position_type"] == position_type and order["exit_type"] == order_type:
|
|
188
|
+
return True
|
|
189
|
+
else:
|
|
190
|
+
if order["strike_price"] == strike_price and order["option_type"] == option_type and order["position_type"] == position_type and order["exit_type"] == order_type and order["order_timestamp"] > entry_time:
|
|
191
|
+
return True
|
|
192
|
+
return False
|
|
193
|
+
except Exception as e:
|
|
194
|
+
print("Exception in checking existing order : {}".format(e))
|
|
195
|
+
pass
|
|
196
|
+
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import datetime
|
|
3
|
+
import json
|
|
4
|
+
from sysstra.orders.common import add_order_to_redis, fetch_orders_list
|
|
5
|
+
from sysstra.utils import send_order_alert
|
|
6
|
+
from sysstra import orders_url
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def place_lt_order(tradingsymbol, quantity, transaction_type, order_type, lot_size=15, exchange="NSE",
|
|
10
|
+
credential_id=None, trigger_price=None, order_price=None):
|
|
11
|
+
""" Function to Place Live Trading Order """
|
|
12
|
+
try:
|
|
13
|
+
|
|
14
|
+
if order_type == "MARKET":
|
|
15
|
+
order_data_params = {"tradingsymbol": tradingsymbol,
|
|
16
|
+
"exchange": exchange,
|
|
17
|
+
"transaction_type": transaction_type,
|
|
18
|
+
"quantity": quantity * lot_size,
|
|
19
|
+
"order_type": order_type,
|
|
20
|
+
"product": "MIS",
|
|
21
|
+
"validity": "DAY"}
|
|
22
|
+
|
|
23
|
+
order_response = place_live_order(credential_id=credential_id, order_details=order_data_params)
|
|
24
|
+
|
|
25
|
+
if order_response["status"] == "COMPLETE":
|
|
26
|
+
# return "success", order_response["broker_response"][0]["broker_response"]
|
|
27
|
+
return "success", order_response
|
|
28
|
+
else:
|
|
29
|
+
return "failed", None
|
|
30
|
+
|
|
31
|
+
elif order_type == "SL":
|
|
32
|
+
order_data_params = {"tradingsymbol": tradingsymbol, "exchange": exchange,
|
|
33
|
+
"transaction_type": transaction_type,
|
|
34
|
+
"quantity": quantity * lot_size, "product": "MIS", "validity": "DAY",
|
|
35
|
+
"order_type": "SL", "trigger_price": trigger_price, "price": order_price}
|
|
36
|
+
order_response = place_live_order(credential_id=credential_id, order_details=order_data_params)
|
|
37
|
+
|
|
38
|
+
if order_response["status"] == "success":
|
|
39
|
+
# return "success", order_response["data"]["order_id"]
|
|
40
|
+
# return "success", order_response["order_id"][0]
|
|
41
|
+
return "success", order_response["order_id"]
|
|
42
|
+
else:
|
|
43
|
+
return "failed", None
|
|
44
|
+
|
|
45
|
+
elif order_type == "LIMIT":
|
|
46
|
+
order_data_params = {"tradingsymbol": tradingsymbol, "exchange": exchange,
|
|
47
|
+
"transaction_type": transaction_type, "quantity": quantity * lot_size,
|
|
48
|
+
"product": "MIS", "validity": "TTL", "validity_ttl": 1,
|
|
49
|
+
"order_type": "LIMIT", "price": order_price}
|
|
50
|
+
|
|
51
|
+
order_response = place_live_order(credential_id=credential_id, order_details=order_data_params)
|
|
52
|
+
|
|
53
|
+
if order_response["status"] == "success":
|
|
54
|
+
# return "success", order_response["data"]["order_id"]
|
|
55
|
+
# return "success", order_response["order_id"][0]
|
|
56
|
+
return "success", order_response["order_id"]
|
|
57
|
+
else:
|
|
58
|
+
return "failed", None
|
|
59
|
+
|
|
60
|
+
except Exception as e:
|
|
61
|
+
print(f"Exception in placing live trade : {e}")
|
|
62
|
+
return "failed", None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def save_lt_order(app_db_cursor, rdb_cursor, tradingsymbol, option_type, strike_price, position_type, quantity, transaction_type, order_type,
|
|
66
|
+
orders_list, exit_type=None, quantity_left=0, params=None, market_type="cash", trade_type=None,
|
|
67
|
+
expiry=None, trigger_price=None, lot_size=25, user_id=None, strategy_id=None, request_id=None,
|
|
68
|
+
exchange="NSE", exchange_timestamp=None, order_id=None, broker_response=None, sl_order_id=None):
|
|
69
|
+
|
|
70
|
+
"""Function to save order in Database"""
|
|
71
|
+
try:
|
|
72
|
+
order_dict = {"exchange": exchange, "user_id": user_id, "strategy_id": strategy_id,
|
|
73
|
+
"request_id": request_id, "tradingsymbol": tradingsymbol, "transaction_type": transaction_type,
|
|
74
|
+
"quantity": quantity, "position_type": position_type, "order_type": order_type,
|
|
75
|
+
"exit_type": exit_type, "quantity_left": quantity_left, "lot_size": lot_size, "trade_type": trade_type,
|
|
76
|
+
"trade_action": trade_type,
|
|
77
|
+
"exchange_timestamp": exchange_timestamp, "status": "COMPLETE", "trigger_price": trigger_price, "order_id": order_id}
|
|
78
|
+
|
|
79
|
+
if sl_order_id:
|
|
80
|
+
order_dict["sl_order_id"] = sl_order_id
|
|
81
|
+
|
|
82
|
+
if market_type == "cash":
|
|
83
|
+
order_dict["expiry"] = ""
|
|
84
|
+
order_dict["option_type"] = ""
|
|
85
|
+
order_dict["strike_price"] = ""
|
|
86
|
+
else:
|
|
87
|
+
order_dict["expiry"] = expiry
|
|
88
|
+
order_dict["option_type"] = option_type
|
|
89
|
+
order_dict["strike_price"] = strike_price
|
|
90
|
+
|
|
91
|
+
order_dict["order_timestamp"] = exchange_timestamp
|
|
92
|
+
order_dict["date"] = datetime.datetime.strptime(str(datetime.datetime.today().date()), '%Y-%m-%d')
|
|
93
|
+
order_dict["day"] = order_dict["date"].strftime("%A")
|
|
94
|
+
|
|
95
|
+
if params:
|
|
96
|
+
order_dict.update(params)
|
|
97
|
+
|
|
98
|
+
# Creating New Dict for saving data in to db
|
|
99
|
+
lt_order_dict = {}
|
|
100
|
+
for key in order_dict.keys():
|
|
101
|
+
lt_order_dict[key] = order_dict[key]
|
|
102
|
+
|
|
103
|
+
lt_order_dict["order_id"] = order_id
|
|
104
|
+
lt_order_dict["broker_response"] = broker_response
|
|
105
|
+
lt_order_dict["trade_action"] = lt_order_dict["trade_type"]
|
|
106
|
+
|
|
107
|
+
# Saving Order Details to Database
|
|
108
|
+
app_db_cursor["lt_orders"].insert_one(lt_order_dict)
|
|
109
|
+
|
|
110
|
+
order_dict["strategy_id"] = str(order_dict["strategy_id"])
|
|
111
|
+
order_dict["request_id"] = str(order_dict["request_id"])
|
|
112
|
+
order_dict["user_id"] = str(order_dict["user_id"])
|
|
113
|
+
order_dict["order_timestamp"] = str(order_dict["order_timestamp"])
|
|
114
|
+
order_dict["exchange_timestamp"] = str(order_dict["exchange_timestamp"])
|
|
115
|
+
order_dict["expiry"] = str(order_dict["expiry"])
|
|
116
|
+
order_dict["date"] = str(order_dict["date"])
|
|
117
|
+
order_dict["order_id"] = order_id
|
|
118
|
+
|
|
119
|
+
add_order_to_redis(rdb_cursor=rdb_cursor, request_id=str(request_id), order_dict=order_dict, mode="lt")
|
|
120
|
+
orders_list = fetch_orders_list(rdb_cursor=rdb_cursor, request_id=str(request_id))
|
|
121
|
+
|
|
122
|
+
# Creating Alert Dict
|
|
123
|
+
alert_dict = {"user_id": str(order_dict["user_id"]),
|
|
124
|
+
"strategy_id": str(order_dict["strategy_id"]),
|
|
125
|
+
"request_id": str(order_dict["request_id"]),
|
|
126
|
+
"mode": "lt",
|
|
127
|
+
"exit_type": exit_type,
|
|
128
|
+
"symbol": tradingsymbol,
|
|
129
|
+
"quantity": quantity,
|
|
130
|
+
"price": trigger_price,
|
|
131
|
+
"quantity_left": quantity_left,
|
|
132
|
+
"trade_type": trade_type,
|
|
133
|
+
"template_id": 0
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Sending Alert
|
|
137
|
+
send_order_alert(alert_dict)
|
|
138
|
+
return "success", orders_list
|
|
139
|
+
|
|
140
|
+
except Exception as e:
|
|
141
|
+
print(f"Exception in Saving Order in DB : {e}")
|
|
142
|
+
return "failed", orders_list
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def save_lt_trade(app_db_cursor, trade_dict):
|
|
146
|
+
"""Function to save order in Database"""
|
|
147
|
+
try:
|
|
148
|
+
# logger.info(msg="* saving LT trade to DB *****")
|
|
149
|
+
app_db_cursor["lt_trades"].insert_one(trade_dict)
|
|
150
|
+
except Exception as e:
|
|
151
|
+
print(f"Exception in saving LT trade in DB : {e}")
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def place_live_order(credential_id, order_details):
|
|
156
|
+
"""Function to place live trade order via REST API"""
|
|
157
|
+
try:
|
|
158
|
+
print("Placing Live Trade Order")
|
|
159
|
+
request_dict = {"credential_id": str(credential_id),
|
|
160
|
+
"order_details": json.dumps(order_details)}
|
|
161
|
+
print("request_dict : {}".format(request_dict))
|
|
162
|
+
|
|
163
|
+
response = requests.post(url=orders_url+"place_order", params=request_dict)
|
|
164
|
+
print("******** Order Placement Response *********")
|
|
165
|
+
print(response.json())
|
|
166
|
+
return response.json()
|
|
167
|
+
except Exception as e:
|
|
168
|
+
print("Exception in placing live trade order : {}".format(e))
|
|
169
|
+
return None
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def modify_live_order(credential_id, order_details):
|
|
173
|
+
"""Function to Modify Live Order"""
|
|
174
|
+
try:
|
|
175
|
+
print("* Modifying Live Order")
|
|
176
|
+
request_dict = {"credential_id": str(credential_id),
|
|
177
|
+
"order_details": json.dumps(order_details)}
|
|
178
|
+
print("request_dict : {}".format(request_dict))
|
|
179
|
+
|
|
180
|
+
response = requests.post(url=orders_url + "modify_order", params=request_dict)
|
|
181
|
+
print("******** Order Placement Response *********")
|
|
182
|
+
print(response.json())
|
|
183
|
+
return response.json()
|
|
184
|
+
except Exception as e:
|
|
185
|
+
print("Exception in Modify Live Order : {}".format(e))
|
|
186
|
+
pass
|