├── .gitignore
├── setup.cfg
├── .idea
├── .gitignore
├── vcs.xml
├── encodings.xml
├── modules.xml
├── misc.xml
├── ig-markets-api-python-library-master.iml
└── inspectionProfiles
│ └── Project_Default.xml
├── .DS_Store
├── requirements-test.txt
├── trading_ig
├── ._utils.py
├── ._config.py
├── ._stream.py
├── ._version.py
├── .___init__.py
├── ._lightstreamer.py
├── __pycache__
│ ├── rest.cpython-36.pyc
│ ├── rest.cpython-37.pyc
│ ├── rest.cpython-39.pyc
│ ├── utils.cpython-36.pyc
│ ├── utils.cpython-37.pyc
│ ├── utils.cpython-39.pyc
│ ├── __init__.cpython-36.pyc
│ ├── __init__.cpython-37.pyc
│ ├── __init__.cpython-39.pyc
│ ├── config.cpython-36.pyc
│ ├── config.cpython-37.pyc
│ ├── config.cpython-39.pyc
│ ├── stream.cpython-36.pyc
│ ├── stream.cpython-37.pyc
│ ├── stream.cpython-39.pyc
│ ├── lightstreamer.cpython-36.pyc
│ ├── lightstreamer.cpython-37.pyc
│ └── lightstreamer.cpython-39.pyc
├── __init__.py
├── config.py
├── stream.py
└── utils.py
├── tests
├── ._test_ig_service.py
├── data
│ ├── switch.json
│ ├── session.json
│ ├── accounts.json
│ ├── accounts_balances.json
│ ├── workingorders.json
│ ├── historic_prices_v1.json
│ ├── historic_prices_dates.json
│ ├── historic_prices_v2.json
│ ├── historic_prices.json
│ └── historic_prices_num_points.json
├── youtube_tut
│ ├── order_lookup.py
│ ├── deleting_orders.py
│ ├── temp_algo_controller.py
│ ├── order_generation.py
│ ├── closing_position.py
│ ├── position_generation.py
│ └── lookup_position.py
├── test_utils.py
├── test_accounts.py
├── test_dealing.py
├── setup.py
└── test_ig_service.py
├── requirements.txt
├── get_data
├── __pycache__
│ ├── get_market_data.cpython-37.pyc
│ └── get_market_data.cpython-39.pyc
└── get_market_data.py
├── sending_orders
├── __pycache__
│ ├── order_management.cpython-37.pyc
│ └── order_management.cpython-39.pyc
├── rest_ig_sending_orders.py
└── order_management.py
├── getting_realtime_data
├── __pycache__
│ ├── data_retrieval.cpython-37.pyc
│ └── data_retrieval.cpython-39.pyc
├── stream_ig_getting_realtime_data.py
└── data_retrieval.py
├── predefined_functions
├── __pycache__
│ ├── initialisation.cpython-37.pyc
│ ├── initialisation.cpython-39.pyc
│ ├── defined_functionality.cpython-37.pyc
│ ├── defined_functionality.cpython-39.pyc
│ └── algo_close_positons_in_profit.cpython-37.pyc
├── initialisation.py
├── algo_creating_working_orders_at_open_on_both_side_quick_functions.py
├── temp_algo_tut.py
├── algo_doing_simple_tasks.py
├── algo_minute_on_quotes.py
├── algo_close_positons_in_profit.py
├── algo_ten_minute.py
└── algo_catch_trends_from_different_markets.py
├── management_of_position
├── __pycache__
│ ├── position_management.cpython-37.pyc
│ └── position_management.cpython-39.pyc
└── position_management.py
├── trading_ig_config.py
├── runAlgo_single_instrument
└── controller_functionality.py
├── tox.ini
├── runAlgo_StopLoss
└── controller_functionality.py
├── runAlgo_Take_Opposite_position_over_sharp_price_changes
├── controller_functionality.py
└── controller_functionality_historical_data.py
├── runAlgo_Create_Working_Orders_on_both_side_at_opening
├── controller_functionality_quick_functions.py
└── controller_functionality.py
├── algo_arbitrage_eur_gbp
└── controller_arbitrage_0.py
├── .github
└── FUNDING.yml
├── positions_on_both_sides
└── controller_functionality.py
├── LICENSE
├── README.md
├── getting_historical_data
├── data_retrieval_historical.py
└── rest_ig_get_historical_data.py
├── sample
├── stream_ig.py
├── stream_stock_list_demo.py
└── rest_ig.py
├── getting_instrument_based_data
├── update_instrument_data_IG.py
└── rest_ig_get_instrument_data.py
├── setup.py
├── Linked_to_biggest_previous_day_difference_in_price
├── adding_all_realtime_IG_data_to_file.py
└── adding_realtime_IG_data_to_file.py
└── Data
└── CFDs
└── instrument_details_SECTORS.csv
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [bdist_wheel]
2 | universal = 1
3 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/.DS_Store
--------------------------------------------------------------------------------
/requirements-test.txt:
--------------------------------------------------------------------------------
1 | pytest
2 | nose
3 | pandas
4 | requests
5 | requests-cache
6 | munch
7 | six
8 |
--------------------------------------------------------------------------------
/trading_ig/._utils.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/._utils.py
--------------------------------------------------------------------------------
/trading_ig/._config.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/._config.py
--------------------------------------------------------------------------------
/trading_ig/._stream.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/._stream.py
--------------------------------------------------------------------------------
/trading_ig/._version.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/._version.py
--------------------------------------------------------------------------------
/tests/._test_ig_service.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/tests/._test_ig_service.py
--------------------------------------------------------------------------------
/trading_ig/.___init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/.___init__.py
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | munch==2.5.0
2 | pycryptodome==3.9.8
3 | requests==2.24.0
4 | requests-cache==0.5.2
5 | six==1.15.0
6 | pandas==1.0.5
7 |
--------------------------------------------------------------------------------
/trading_ig/._lightstreamer.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/._lightstreamer.py
--------------------------------------------------------------------------------
/trading_ig/__pycache__/rest.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/rest.cpython-36.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/rest.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/rest.cpython-37.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/rest.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/rest.cpython-39.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/utils.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/utils.cpython-36.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/utils.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/utils.cpython-37.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/utils.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/utils.cpython-39.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/config.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/config.cpython-36.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/config.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/config.cpython-37.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/config.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/config.cpython-39.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/stream.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/stream.cpython-36.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/stream.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/stream.cpython-37.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/stream.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/stream.cpython-39.pyc
--------------------------------------------------------------------------------
/get_data/__pycache__/get_market_data.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/get_data/__pycache__/get_market_data.cpython-37.pyc
--------------------------------------------------------------------------------
/get_data/__pycache__/get_market_data.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/get_data/__pycache__/get_market_data.cpython-39.pyc
--------------------------------------------------------------------------------
/tests/data/switch.json:
--------------------------------------------------------------------------------
1 | {
2 | "trailingStopsEnabled": true,
3 | "dealingEnabled": true,
4 | "hasActiveDemoAccounts": true,
5 | "hasActiveLiveAccounts": true
6 | }
--------------------------------------------------------------------------------
/trading_ig/__pycache__/lightstreamer.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/lightstreamer.cpython-36.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/lightstreamer.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/lightstreamer.cpython-37.pyc
--------------------------------------------------------------------------------
/trading_ig/__pycache__/lightstreamer.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/trading_ig/__pycache__/lightstreamer.cpython-39.pyc
--------------------------------------------------------------------------------
/sending_orders/__pycache__/order_management.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/sending_orders/__pycache__/order_management.cpython-37.pyc
--------------------------------------------------------------------------------
/sending_orders/__pycache__/order_management.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/sending_orders/__pycache__/order_management.cpython-39.pyc
--------------------------------------------------------------------------------
/getting_realtime_data/__pycache__/data_retrieval.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/getting_realtime_data/__pycache__/data_retrieval.cpython-37.pyc
--------------------------------------------------------------------------------
/getting_realtime_data/__pycache__/data_retrieval.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/getting_realtime_data/__pycache__/data_retrieval.cpython-39.pyc
--------------------------------------------------------------------------------
/predefined_functions/__pycache__/initialisation.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/predefined_functions/__pycache__/initialisation.cpython-37.pyc
--------------------------------------------------------------------------------
/predefined_functions/__pycache__/initialisation.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/predefined_functions/__pycache__/initialisation.cpython-39.pyc
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/management_of_position/__pycache__/position_management.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/management_of_position/__pycache__/position_management.cpython-37.pyc
--------------------------------------------------------------------------------
/management_of_position/__pycache__/position_management.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/management_of_position/__pycache__/position_management.cpython-39.pyc
--------------------------------------------------------------------------------
/predefined_functions/__pycache__/defined_functionality.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/predefined_functions/__pycache__/defined_functionality.cpython-37.pyc
--------------------------------------------------------------------------------
/predefined_functions/__pycache__/defined_functionality.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/predefined_functions/__pycache__/defined_functionality.cpython-39.pyc
--------------------------------------------------------------------------------
/tests/youtube_tut/order_lookup.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.defined_functionality import Defined_Functionality
2 |
3 |
4 | df = Defined_Functionality()
5 |
6 | orders = df.get_working_orders()
7 |
8 | print("stop")
9 |
--------------------------------------------------------------------------------
/predefined_functions/__pycache__/algo_close_positons_in_profit.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g-make-it/IG_Trading_Algo_Scripts_Python/HEAD/predefined_functions/__pycache__/algo_close_positons_in_profit.cpython-37.pyc
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/data/session.json:
--------------------------------------------------------------------------------
1 | {
2 | "clientId": "100112233",
3 | "accountId": "ABC123",
4 | "timezoneOffset": 1,
5 | "locale": "en_GB",
6 | "currency": "GBP",
7 | "lightstreamerEndpoint": "https://demo-apd.marketdatasystems.com"
8 | }
--------------------------------------------------------------------------------
/tests/youtube_tut/deleting_orders.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.defined_functionality import Defined_Functionality
2 |
3 |
4 | df = Defined_Functionality()
5 |
6 | orders = df.get_working_orders()
7 |
8 | df.cancel_orders_by_epic("IX.D.NASDAQ.CASH.IP")
9 |
10 | print("stop")
11 |
--------------------------------------------------------------------------------
/trading_ig_config.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #-*- coding:utf-8 -*-
3 |
4 |
5 | class config(object):
6 | username = "YOUR_USERNAME"
7 | password = "YOUR_PASSWORD"
8 | api_key = "YOUR_API_KEY"
9 | acc_type = "DEMO" # LIVE / DEMO
10 | acc_number = "ABC123"
11 |
--------------------------------------------------------------------------------
/tests/youtube_tut/temp_algo_controller.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.temp_algo_tut import Algo0
2 |
3 |
4 | class Controller_Functionality:
5 |
6 | def run(self):
7 | algo = Algo0()
8 | algo.run()
9 |
10 |
11 | if __name__ == '__main__':
12 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/runAlgo_single_instrument/controller_functionality.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.algo_creating_working_orders_for_only_one_instrument import Algo0
2 |
3 | class Controller_Functionality:
4 |
5 |
6 | def run(self):
7 | algo = Algo0()
8 | algo.run()
9 |
10 |
11 |
12 |
13 |
14 |
15 | if __name__ == '__main__':
16 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | # Tox (http://tox.testrun.org/) is a tool for running tests
2 | # in multiple virtualenvs. This configuration file will run the
3 | # test suite on all supported python versions. To use it, "pip install tox"
4 | # and then run "tox" from this directory.
5 |
6 | [tox]
7 | envlist = py27, py33
8 |
9 | [testenv]
10 | commands = nosetests -s -v
11 | deps =
12 | nose
13 |
--------------------------------------------------------------------------------
/tests/youtube_tut/order_generation.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.defined_functionality import Defined_Functionality
2 |
3 |
4 | df = Defined_Functionality()
5 |
6 | order = df.create_working_order(epic="IX.D.NASDAQ.CASH.IP", direction="BUY",size=1, force_open=True)
7 | # if you have force_open == True = limits for your orders will not work - and it will throw you an error - order being rejected
8 | print("stop")
9 |
--------------------------------------------------------------------------------
/tests/youtube_tut/closing_position.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.defined_functionality import Defined_Functionality
2 |
3 |
4 | df = Defined_Functionality()
5 |
6 |
7 | position = df.create_open_position(epic="IX.D.NASDAQ.CASH.IP", direction="BUY",size=1, force_open=True, guaranteed_stop=False, min_limit_stop=False)
8 | positions = df.get_open_positions()
9 | print("stop")
10 | output = df.close_position(position=positions[0])
11 | print("stop")
12 |
--------------------------------------------------------------------------------
/runAlgo_StopLoss/controller_functionality.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.initialisation import Initialisation
2 | from predefined_functions.algo_close_positons_in_profit import Algo0
3 |
4 | class Controller_Functionality:
5 | # def __init__(self):
6 | # intial = Initialisation()
7 | # self.initial = intial.initialise_connection()
8 |
9 |
10 | def run(self):
11 | algo = Algo0()
12 | algo.run()
13 |
14 |
15 |
16 |
17 |
18 |
19 | if __name__ == '__main__':
20 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/tests/youtube_tut/position_generation.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.defined_functionality import Defined_Functionality
2 |
3 |
4 | df = Defined_Functionality()
5 |
6 | # order = df.create_open_position(epic="IX.D.NASDAQ.CASH.IP", direction="BUY",size=1, force_open=True)
7 | order = df.create_open_position(epic="IX.D.NASDAQ.CASH.IP", direction="BUY",size=1, force_open=True, guaranteed_stop=False, min_limit_stop=False)
8 | # if you have force_open == True = limits for your orders will not work - and it will throw you an error - order being rejected
9 | print("stop")
10 |
--------------------------------------------------------------------------------
/runAlgo_Take_Opposite_position_over_sharp_price_changes/controller_functionality.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.initialisation import Initialisation
2 | from predefined_functions.algo_opposing_position_on_sharp_price_changes import Algo0
3 |
4 | class Controller_Functionality:
5 | # def __init__(self):
6 | # intial = Initialisation()
7 | # self.initial = intial.initialise_connection()
8 |
9 |
10 | def run(self):
11 | algo = Algo0()
12 | algo.run()
13 |
14 |
15 |
16 |
17 |
18 |
19 | if __name__ == '__main__':
20 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/tests/test_utils.py:
--------------------------------------------------------------------------------
1 | from trading_ig.utils import conv_datetime
2 |
3 | """
4 | Unit tests for utils module
5 | """
6 |
7 |
8 | class TestUtils:
9 |
10 | def test_conv_datetime_format_1(self):
11 | result = conv_datetime('2020/03/01', 1)
12 | assert result == '2020:03:01-00:00:00'
13 |
14 | def test_conv_datetime_format_2(self):
15 | result = conv_datetime('2020/03/01', 2)
16 | assert result == '2020/03/01 00:00:00'
17 |
18 | def test_conv_datetime_format_3(self):
19 | result = conv_datetime('2020/03/01', 3)
20 | assert result == '2020/03/01 00:00:00'
21 |
--------------------------------------------------------------------------------
/.idea/ig-markets-api-python-library-master.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/runAlgo_Create_Working_Orders_on_both_side_at_opening/controller_functionality_quick_functions.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.initialisation import Initialisation
2 | from predefined_functions.algo_creating_working_orders_at_open_on_both_side_quick_functions import Algo0
3 |
4 | class Controller_Functionality:
5 | # def __init__(self):
6 | # intial = Initialisation()
7 | # self.initial = intial.initialise_connection()
8 |
9 |
10 | def run(self):
11 | algo = Algo0()
12 | algo.run()
13 |
14 |
15 |
16 |
17 |
18 |
19 | if __name__ == '__main__':
20 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/runAlgo_Take_Opposite_position_over_sharp_price_changes/controller_functionality_historical_data.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.initialisation import Initialisation
2 | from predefined_functions.algo_opposing_position_on_sharp_price_changes_based_on_historical_data import Algo0
3 |
4 | class Controller_Functionality:
5 | # def __init__(self):
6 | # intial = Initialisation()
7 | # self.initial = intial.initialise_connection()
8 |
9 |
10 | def run(self):
11 | algo = Algo0()
12 | algo.run()
13 |
14 |
15 |
16 |
17 |
18 |
19 | if __name__ == '__main__':
20 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/algo_arbitrage_eur_gbp/controller_arbitrage_0.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.initialisation import Initialisation
2 | # from algo_arbitrage.trianglar_arbitrage_spreadbetting import Algo0
3 | from algo_arbitrage_eur_gbp.trianglar_arbitrage_spreadbetting_exiting_out_incrementally import Algo0
4 |
5 | class Controller_Functionality:
6 | # def __init__(self):
7 | # intial = Initialisation()
8 | # self.initial = intial.initialise_connection()
9 |
10 |
11 | def run(self):
12 | EURGBP = "CS.D.EURGBP.TODAY.IP"
13 | GBPEUR = "CS.D.GBPEUR.TODAY.IP"
14 | algo = Algo0(EURGBP=EURGBP, GBPEUR=GBPEUR)
15 | algo.run()
16 |
17 |
18 |
19 |
20 |
21 |
22 | if __name__ == '__main__':
23 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom: ['https://www.paypal.com/donate?hosted_button_id=WAJRVR3TBB4FN']
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 |
--------------------------------------------------------------------------------
/tests/youtube_tut/lookup_position.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.defined_functionality import Defined_Functionality
2 | import time
3 |
4 |
5 | df = Defined_Functionality()
6 |
7 | # # order = df.create_open_position(epic="IX.D.NASDAQ.CASH.IP", direction="BUY",size=1, force_open=True)
8 | # order = df.create_open_position(epic="IX.D.NASDAQ.CASH.IP", direction="BUY",size=1, force_open=True, guaranteed_stop=False, min_limit_stop=False)
9 | # # if you have force_open == True = limits for your orders will not work - and it will throw you an error - order being rejected
10 | #
11 | # print("stop")
12 |
13 | positions_list = df.get_open_positions()
14 |
15 | print("stop")
16 |
17 |
18 | # while(True):
19 | # positions_list = df.get_open_positions()
20 | # print((positions_list[0])["position"]["openLevel"] - (positions_list[0])["market"]["offer"])
21 | # time.sleep()
--------------------------------------------------------------------------------
/trading_ig/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | IG Markets API Library for Python
6 | https://github.com/ig-python/ig-markets-api-python-library/
7 | by Femto Trader - https://github.com/femtotrader
8 | """
9 |
10 | from __future__ import absolute_import, division, print_function
11 |
12 |
13 | from .version import (
14 | __author__,
15 | __copyright__,
16 | __credits__,
17 | __license__,
18 | __version__,
19 | __maintainer__,
20 | __author_email__,
21 | __status__,
22 | __url__,
23 | )
24 |
25 | from .rest import IGService
26 | from .stream import IGStreamService
27 |
28 | __all__ = [
29 | "IGService",
30 | "IGStreamService",
31 | "__author__",
32 | "__copyright__",
33 | "__credits__",
34 | "__license__",
35 | "__version__",
36 | "__maintainer__",
37 | "__author_email__",
38 | "__status__",
39 | "__url__",
40 | ]
41 |
--------------------------------------------------------------------------------
/runAlgo_Create_Working_Orders_on_both_side_at_opening/controller_functionality.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.initialisation import Initialisation
2 | from predefined_functions.algo_creating_working_orders_at_open_on_both_side import Algo0
3 |
4 | class Controller_Functionality:
5 | # def __init__(self):
6 | # intial = Initialisation()
7 | # self.initial = intial.initialise_connection()
8 |
9 |
10 | def run(self):
11 | algo = Algo0()
12 | algo.run()
13 |
14 |
15 |
16 |
17 |
18 |
19 | if __name__ == '__main__':
20 | # run these program independently:
21 | # runAlgoStopLoss: - risk management
22 | # runAlgo_Create_Working_Orders_on_both_side_at_opening.controller_functionality_quick_function: make's sure all orders are balanced incase the program below take too long
23 | # and this one - creates the orders and works out the signal and instruments that we create orders for
24 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/positions_on_both_sides/controller_functionality.py:
--------------------------------------------------------------------------------
1 | # from predefined_functions.defined_functionality import Defined_Functionality
2 | from predefined_functions.initialisation import Initialisation
3 | # from predefined_functions.algo_ten_minute import Algo0 -- old one
4 | # from predefined_functions.algo_minute_on_quotes import Algo0 -- old one
5 | from predefined_functions.algo_positions_on_both_sides import Algo0
6 | # from predefined_functions.algo_catch_trends_from_different_markets import Algo0
7 | # from predefined_functions.algo_arbitration_between_two_instruments import Algo0
8 |
9 | class Controller_Functionality:
10 | def __init__(self):
11 | intial = Initialisation()
12 | self.initial = intial.initialise_connection()
13 |
14 |
15 | def run(self):
16 | algo = Algo0()
17 | algo.run()
18 | pass
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | if __name__ == '__main__':
30 |
31 | Controller_Functionality().run()
--------------------------------------------------------------------------------
/tests/data/accounts.json:
--------------------------------------------------------------------------------
1 | {
2 | "accountType": "SPREADBET",
3 | "accountInfo": {
4 | "balance": 1000.00,
5 | "deposit": 500.00,
6 | "profitLoss": 500.00,
7 | "available": 1000.00
8 | },
9 | "currencyIsoCode": "GBP",
10 | "currencySymbol": "£",
11 | "currentAccountId": "ABC123",
12 | "lightstreamerEndpoint": "https://demo-apd.marketdatasystems.com",
13 | "accounts": [
14 | {
15 | "accountId": "ABC123",
16 | "accountName": "Demo-SpreadBet",
17 | "preferred": true,
18 | "accountType": "SPREADBET"
19 | },
20 | {
21 | "accountId": "XYZ987",
22 | "accountName": "Demo-cfd",
23 | "preferred": false,
24 | "accountType": "CFD"
25 | }
26 | ],
27 | "clientId": "20007685858",
28 | "timezoneOffset": 0,
29 | "hasActiveDemoAccounts": true,
30 | "hasActiveLiveAccounts": true,
31 | "trailingStopsEnabled": true,
32 | "reroutingEnvironment": null,
33 | "dealingEnabled": true
34 | }
--------------------------------------------------------------------------------
/tests/data/accounts_balances.json:
--------------------------------------------------------------------------------
1 | {
2 | "accounts": [
3 | {
4 | "accountId": "XYZ987",
5 | "accountName": "Demo-SpreadBet",
6 | "accountAlias": null,
7 | "status": "ENABLED",
8 | "accountType": "SPREADBET",
9 | "preferred": false,
10 | "balance": {
11 | "balance": 1000.00,
12 | "deposit": 500.00,
13 | "profitLoss": 500.00,
14 | "available": 1000.00
15 | },
16 | "currency": "GBP",
17 | "canTransferFrom": true,
18 | "canTransferTo": true
19 | },
20 | {
21 | "accountId": "ABC123",
22 | "accountName": "Demo-cfd",
23 | "accountAlias": null,
24 | "status": "ENABLED",
25 | "accountType": "CFD",
26 | "preferred": true,
27 | "balance": null,
28 | "currency": "GBP",
29 | "canTransferFrom": true,
30 | "canTransferTo": true
31 | }
32 | ]
33 | }
--------------------------------------------------------------------------------
/tests/test_accounts.py:
--------------------------------------------------------------------------------
1 | from trading_ig.rest import IGService
2 | import responses
3 | import json
4 | import pandas as pd
5 |
6 | """
7 | unit tests for accounts methods
8 | """
9 |
10 |
11 | class TestAccounts:
12 |
13 | # fetch_accounts
14 |
15 | @responses.activate
16 | def test_fetch_accounts_happy(self):
17 |
18 | with open('tests/data/accounts_balances.json', 'r') as file:
19 | response_body = json.loads(file.read())
20 |
21 | responses.add(responses.GET, 'https://demo-api.ig.com/gateway/deal/accounts',
22 | headers={'CST': 'abc123', 'X-SECURITY-TOKEN': 'xyz987'},
23 | json=response_body,
24 | status=200)
25 |
26 | ig_service = IGService('username', 'password', 'api_key', 'DEMO')
27 | ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
28 | result = ig_service.fetch_accounts()
29 |
30 | pd.set_option('display.max_columns', 13)
31 | print(result)
32 |
33 | assert isinstance(result, pd.DataFrame)
34 | assert result.iloc[0]['accountId'] == 'XYZ987'
35 | assert result.iloc[0]['balance'] == 1000.0
36 | assert result.iloc[1]['accountId'] == 'ABC123'
37 | assert pd.isna(result.iloc[1]['balance'])
38 | assert pd.isna(result.iloc[1]['deposit'])
39 |
--------------------------------------------------------------------------------
/tests/test_dealing.py:
--------------------------------------------------------------------------------
1 | from trading_ig.rest import IGService
2 | import responses
3 | import json
4 | import pandas as pd
5 |
6 | """
7 | unit tests for dealing methods
8 | """
9 |
10 |
11 | class TestDealing:
12 |
13 | # login v1
14 |
15 | @responses.activate
16 | def test_workingorders_happy(self):
17 |
18 | with open('tests/data/workingorders.json', 'r') as file:
19 | response_body = json.loads(file.read())
20 |
21 | responses.add(responses.GET,
22 | 'https://demo-api.ig.com/gateway/deal/workingorders',
23 | headers={'CST': 'abc123', 'X-SECURITY-TOKEN': 'xyz987'},
24 | json=response_body,
25 | status=200)
26 |
27 | ig_service = IGService('username', 'password', 'api_key', 'DEMO')
28 | ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
29 | result = ig_service.fetch_working_orders()
30 |
31 | pd.set_option('display.max_columns', 50)
32 | print(result)
33 |
34 | assert isinstance(result, pd.DataFrame)
35 | assert result.iloc[0]['instrumentName'] == 'Spot Gold'
36 | assert result.iloc[0]['exchangeId'] == 'FX_C_GCSI_ST'
37 | assert result.iloc[0]['marketStatus'] == 'EDITS_ONLY'
38 | assert result.iloc[0]['level'] == 2000.0
39 | assert result.iloc[0]['epic'] == 'CS.D.CFDGOLD.CFDGC.IP'
40 | assert result.iloc[0]['currencyCode'] == 'USD'
41 |
--------------------------------------------------------------------------------
/trading_ig/config.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | import os
5 | import logging
6 |
7 | ENV_VAR_ROOT = "IG_SERVICE"
8 | CONFIG_FILE_NAME = "trading_ig_config.py"
9 |
10 | logger = logging.getLogger(__name__)
11 |
12 |
13 | class ConfigEnvVar(object):
14 | def __init__(self, env_var_base):
15 | self.ENV_VAR_BASE = env_var_base
16 |
17 | def _env_var(self, key):
18 | return self.ENV_VAR_BASE + "_" + key.upper()
19 |
20 | def get(self, key, default_value=None):
21 | env_var = self._env_var(key)
22 | return os.environ.get(env_var, default_value)
23 |
24 | def __getattr__(self, key):
25 | env_var = self._env_var(key)
26 | try:
27 | return os.environ[env_var]
28 | except KeyError:
29 | raise Exception("Environment variable '%s' doesn't exist" % env_var)
30 |
31 |
32 | try:
33 | from trading_ig_config import config
34 |
35 | logger.info("import config from %s" % CONFIG_FILE_NAME)
36 | except Exception:
37 | logger.warning("can't import config from config file")
38 | try:
39 | config = ConfigEnvVar(ENV_VAR_ROOT)
40 | logger.info("import config from environment variables '%s_...'" % ENV_VAR_ROOT)
41 | except Exception:
42 | logger.warning("can't import config from environment variables")
43 | raise (
44 | """Can't import config - you might create a '%s' filename or use
45 | environment variables such as '%s_...'"""
46 | % (CONFIG_FILE_NAME, ENV_VAR_ROOT)
47 | )
48 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015, femtotrader
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of ig-markets-stream-api-python-library nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 |
--------------------------------------------------------------------------------
/tests/data/workingorders.json:
--------------------------------------------------------------------------------
1 | {
2 | "workingOrders": [
3 | {
4 | "workingOrderData": {
5 | "dealId": "ABCD1234",
6 | "direction": "BUY",
7 | "epic": "CS.D.CFDGOLD.CFDGC.IP",
8 | "size": 0.05,
9 | "level": 2000.00,
10 | "goodTill": "GTC",
11 | "createdDate": "2020/10/01 10:00:00:000",
12 | "controlledRisk": false,
13 | "trailingTriggerIncrement": null,
14 | "trailingTriggerDistance": null,
15 | "trailingStopDistance": null,
16 | "trailingStopIncrement": null,
17 | "requestType": "STOP_ORDER",
18 | "contingentStop": null,
19 | "currencyCode": "USD",
20 | "contingentLimit": null,
21 | "dma": false,
22 | "limitedRiskPremium": null
23 | },
24 | "marketData": {
25 | "instrumentName": "Spot Gold",
26 | "exchangeId": "FX_C_GCSI_ST",
27 | "expiry": "-",
28 | "marketStatus": "EDITS_ONLY",
29 | "epic": "CS.D.CFDGOLD.CFDGC.IP",
30 | "instrumentType": "CURRENCIES",
31 | "lotSize": 100.0,
32 | "high": 1960.0,
33 | "low": 1920.0,
34 | "percentageChange": 0.0,
35 | "netChange": 0.0,
36 | "bid": 1950.00,
37 | "offer": 1951.00,
38 | "updateTime": "2020/10/01 09:00:00:000",
39 | "delayTime": 0,
40 | "streamingPricesAvailable": true,
41 | "scalingFactor": 1
42 | }
43 | }
44 | ]
45 | }
--------------------------------------------------------------------------------
/get_data/get_market_data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | """
5 | IG Markets REST API sample with Python
6 | 2015 FemtoTrader
7 | """
8 |
9 | from trading_ig import IGService
10 | from trading_ig.config import config
11 | import logging
12 | # format to
13 | # # from folder.file import class
14 | # from getting_instrument_based_data.navigate_tree import NavigateTree
15 |
16 | logger = logging.getLogger(__name__)
17 | logger.setLevel(logging.DEBUG)
18 |
19 | # if you need to cache to DB your requests
20 | from datetime import timedelta
21 | import requests_cache
22 | import time
23 | import os
24 | import json
25 |
26 | from predefined_functions.initialisation import Initialisation
27 |
28 | class Get_Market_Data():
29 |
30 | def __init__(self):
31 | self.initial = Initialisation()
32 | self.initialise_connection()
33 |
34 | def initialise_connection(self):
35 | self.ig_service = self.initial.initialise_connection()
36 | self.ig_service.create_session()
37 |
38 | def get_node_to_node_data(self,node):
39 | while(True):
40 | try:
41 | map_dataframe = self.ig_service.fetch_sub_nodes_by_node(node=node)
42 | return map_dataframe
43 | except Exception as e:
44 | print(e)
45 | self.initialise_connection()
46 | # time.sleep(1)
47 |
48 | def get_details_about_epic(self, epic):
49 | try:
50 | map_of_data = self.ig_service.fetch_market_by_epic(epic)
51 | data_string = json.dumps(map_of_data)
52 | data = json.loads(data_string)
53 |
54 | return data
55 | except Exception as e:
56 | print(e)
57 | self.initialise_connection()
58 | # time.sleep(1)
59 |
60 |
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IG_Trading_Algo_Scripts_Python
2 | IG Trading Algos and Scripts in Python
3 |
4 | This project is a collection of my work over 2 years building IG Trading Algorithms + Scripts, and [Donations](https://www.paypal.com/donate?hosted_button_id=WAJRVR3TBB4FN) would be much appreciated.
5 |
6 | The Data Folder holds instrument data, raw and cleaned:
7 | .csv files are intended to be used for pandas dataframes
8 |
9 | The algorithms follow a mvc format each controller calls a algorithm to run (some have been commented out)
10 |
11 | Create a file holding your API keys and state its path in __predefined_functions -> initialisation.py__
12 |
13 | Check the video for more details:
14 |
15 |
16 |
17 | [](https://www.youtube.com/watch?v=joTp_a2sE8c)
18 |
19 | ## Update
20 |
21 | ----------------------------
22 | [](https://www.youtube.com/watch?v=5sxsvN5bv2s)
23 |
24 |
25 | ## [Subscribe](https://www.youtube.com/channel/UCsQqV_wq5yPrw5YIpvwmjvQ) to my youtube channel to find similar content.
26 | ## [Donations](https://www.paypal.com/donate?hosted_button_id=WAJRVR3TBB4FN).
27 |
28 | ------------------------
29 |
30 | ### Just a few more notes:
31 |
32 | The core scripts used in trading_IG (license in root folder) and some of the scripts in test and
33 | the config are from: https://github.com/ig-python/ig-markets-api-python-library
34 |
35 | **All the other scripts + algos have been developed by me.**
36 |
37 | This project has a number of different algorithms, some had interesting results and others not so: The most interesting of those, I’ve documented in my videos:
38 |
39 | https://www.youtube.com/watch?v=9i5Rvi8XLwE - Positions on opposite sides of a single instrument
40 |
41 | https://www.youtube.com/watch?v=VO9KsEVHeBk - Opposite orders on a single instrument - before the market opens
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/predefined_functions/initialisation.py:
--------------------------------------------------------------------------------
1 | from trading_ig import IGService
2 | from trading_ig.config import config
3 | import logging
4 |
5 | logger = logging.getLogger(__name__)
6 | logger.setLevel(logging.DEBUG)
7 |
8 | # if you need to cache to DB your requests
9 | from datetime import timedelta
10 | import requests_cache
11 |
12 |
13 | class Initialisation():
14 | def __init__(self):
15 | logging.basicConfig(level=logging.INFO)
16 |
17 |
18 | self.counter = -1
19 | self.initialise_connection()
20 |
21 | def initialise_connection(self):
22 |
23 | key = self.increment_api_key()
24 |
25 | # expire_after = timedelta(hours=1)
26 | # session = requests_cache.CachedSession(
27 | # cache_name='cache', backend='sqlite', expire_after=expire_after
28 | # )
29 | # set expire_after=None if you don't want cache expiration
30 | # set expire_after=0 if you don't want to cache queries
31 |
32 | # no cache
33 | ig_service = IGService(
34 | config.username, config.password, key, config.acc_type
35 | )
36 | # if you want to globally cache queries
37 | # ig_service = IGService(config.username, config.password, config.api_key, config.acc_type, session)
38 | return ig_service
39 | # make sure once the object is received to the place were it is needed you createSession() to initialise the session
40 |
41 | def increment_api_key(self):
42 | key = ""
43 | while (True):
44 | try:
45 | self.counter += 1
46 | # has 12000 api keys
47 | fp = open("D:\Stock_Analysis\ig-markets-api-python-library-master\generate_api_keys\IG_api_keys_raw.txt")
48 | for i, line in enumerate(fp):
49 | if i == self.counter:
50 | key = line.split("\n")[0]
51 | fp.close()
52 | return key
53 | raise Exception("file has surpassed the last api key")
54 | except:
55 | fp.close()
56 | self.counter = -1
57 |
--------------------------------------------------------------------------------
/trading_ig/stream.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | from __future__ import absolute_import, division, print_function
5 |
6 | import sys
7 | import traceback
8 | import logging
9 |
10 | from .lightstreamer import LSClient
11 |
12 | logger = logging.getLogger(__name__)
13 |
14 |
15 | class IGStreamService(object):
16 | def __init__(self, ig_service):
17 | self.ig_service = ig_service
18 | self.ig_session = None
19 | self.ls_client = None
20 |
21 | def create_session(self, encryption=False):
22 | ig_session = self.ig_service.create_session(encryption=encryption)
23 | self.ig_session = ig_session
24 | return ig_session
25 |
26 | def connect(self, accountId):
27 | cst = self.ig_service.crud_session.CLIENT_TOKEN
28 | xsecuritytoken = self.ig_service.crud_session.SECURITY_TOKEN
29 | lightstreamerEndpoint = self.ig_session[u"lightstreamerEndpoint"]
30 | # clientId = self.ig_session[u'clientId']
31 | ls_password = "CST-%s|XST-%s" % (cst, xsecuritytoken)
32 |
33 | # Establishing a new connection to Lightstreamer Server
34 | logger.info("Starting connection with %s" % lightstreamerEndpoint)
35 | # self.ls_client = LSClient("http://localhost:8080", "DEMO")
36 | # self.ls_client = LSClient("http://push.lightstreamer.com", "DEMO")
37 | self.ls_client = LSClient(
38 | lightstreamerEndpoint, adapter_set="", user=accountId, password=ls_password
39 | )
40 | try:
41 | self.ls_client.connect()
42 | return
43 | except Exception:
44 | logger.error("Unable to connect to Lightstreamer Server")
45 | logger.error(traceback.format_exc())
46 | sys.exit(1)
47 |
48 | def unsubscribe_all(self):
49 | # To avoid a RuntimeError: dictionary changed size during iteration
50 | subscriptions = self.ls_client._subscriptions.copy()
51 | for subcription_key in subscriptions:
52 | self.ls_client.unsubscribe(subcription_key)
53 |
54 | def disconnect(self):
55 | self.unsubscribe_all()
56 | self.ls_client.disconnect()
57 |
--------------------------------------------------------------------------------
/getting_historical_data/data_retrieval_historical.py:
--------------------------------------------------------------------------------
1 | import time
2 | import sys
3 | import traceback
4 | import logging
5 | import math
6 |
7 | from trading_ig import (IGService, IGStreamService)
8 | from trading_ig.config import config
9 | from trading_ig.lightstreamer import Subscription
10 | from predefined_functions.initialisation import Initialisation
11 |
12 | class Data_Retrieval_Historical:
13 | def __init__(self):
14 | self.data_map = {}
15 | self.ig_service = None
16 | self.initial = Initialisation()
17 | self.initialise_connection()
18 |
19 | def initialise_connection(self):
20 | while(True):
21 | try:
22 | self.ig_service = self.initial.initialise_connection()
23 | self.ig_service.create_session()
24 | return
25 | except Exception as e:
26 | print(e)
27 |
28 |
29 |
30 | def get_historical_data_based_date_range(self, epic, resolution, start_date, end_date):
31 | # start_date="2020-04-24"
32 | # end_date = "2020-05-01"
33 | response = None
34 | while (True):
35 | try:
36 | response = self.ig_service.fetch_historical_prices_by_epic_and_date_range(epic=epic, resolution=resolution, start_date=start_date, end_date=end_date)
37 | break
38 | except Exception as e:
39 | # print(e, " there was not data available")
40 | if (str(e) == "error.public-api.exceeded-account-historical-data-allowance") or (
41 | str(e) == "error.security.generic") or (
42 | str(e) == "error.public-api.exceeded-api-key-allowance"):
43 | self.initialise_connection()
44 | continue
45 |
46 | return None
47 |
48 | # print(response)
49 | data_frame_of_prices = response["prices"]
50 |
51 | return data_frame_of_prices
52 |
53 | def get_historical_data_based_num_points(self, epic, resolution, num_points):
54 | response = None
55 | while (True):
56 | try:
57 | response = self.ig_service.fetch_historical_prices_by_epic_and_num_points( epic, resolution, num_points)
58 | break
59 | except Exception as e:
60 | # print(e, " there was not data available")
61 | if (str(e) == "error.public-api.exceeded-account-historical-data-allowance") or (
62 | str(e) == "error.security.generic") or (
63 | str(e) == "error.public-api.exceeded-api-key-allowance"):
64 | self.initialise_connection()
65 | continue
66 |
67 | return None
68 |
69 | # print(response)
70 | data_frame_of_prices = response["prices"]
71 |
72 | return data_frame_of_prices
--------------------------------------------------------------------------------
/sample/stream_ig.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | """
5 | IG Markets Stream API sample with Python
6 | 2015 FemtoTrader
7 | """
8 |
9 | import time
10 | import sys
11 | import traceback
12 | import logging
13 |
14 | from trading_ig import IGService, IGStreamService
15 | from trading_ig.config import config
16 | from trading_ig.lightstreamer import Subscription
17 |
18 |
19 | # A simple function acting as a Subscription listener
20 | def on_prices_update(item_update):
21 | # print("price: %s " % item_update)
22 | print(
23 | "{stock_name:<19}: Time {UPDATE_TIME:<8} - "
24 | "Bid {BID:>5} - Ask {OFFER:>5}".format(
25 | stock_name=item_update["name"], **item_update["values"]
26 | )
27 | )
28 |
29 |
30 | def on_account_update(balance_update):
31 | print("balance: %s " % balance_update)
32 |
33 |
34 | def main():
35 | logging.basicConfig(level=logging.INFO)
36 | # logging.basicConfig(level=logging.DEBUG)
37 |
38 | ig_service = IGService(
39 | config.username, config.password, config.api_key, config.acc_type
40 | )
41 |
42 | ig_stream_service = IGStreamService(ig_service)
43 | ig_session = ig_stream_service.create_session()
44 | # Ensure configured account is selected
45 | accounts = ig_session[u"accounts"]
46 | for account in accounts:
47 | if account[u"accountId"] == config.acc_number:
48 | accountId = account[u"accountId"]
49 | break
50 | else:
51 | print("Account not found: {0}".format(config.acc_number))
52 | accountId = None
53 | ig_stream_service.connect(accountId)
54 |
55 | # Making a new Subscription in MERGE mode
56 | subscription_prices = Subscription(
57 | mode="MERGE",
58 | items=["L1:CS.D.GBPUSD.CFD.IP", "L1:CS.D.USDJPY.CFD.IP"],
59 | fields=["UPDATE_TIME", "BID", "OFFER", "CHANGE", "MARKET_STATE"],
60 | )
61 | # adapter="QUOTE_ADAPTER")
62 |
63 | # Adding the "on_price_update" function to Subscription
64 | subscription_prices.addlistener(on_prices_update)
65 |
66 | # Registering the Subscription
67 | sub_key_prices = ig_stream_service.ls_client.subscribe(subscription_prices)
68 |
69 | # Making an other Subscription in MERGE mode
70 | subscription_account = Subscription(
71 | mode="MERGE", items=["ACCOUNT:" + accountId], fields=["AVAILABLE_CASH"],
72 | )
73 | # #adapter="QUOTE_ADAPTER")
74 |
75 | # Adding the "on_balance_update" function to Subscription
76 | subscription_account.addlistener(on_account_update)
77 |
78 | # Registering the Subscription
79 | sub_key_account = ig_stream_service.ls_client.subscribe(subscription_account)
80 |
81 | input(
82 | "{0:-^80}\n".format(
83 | "HIT CR TO UNSUBSCRIBE AND DISCONNECT FROM \
84 | LIGHTSTREAMER"
85 | )
86 | )
87 |
88 | # Disconnecting
89 | ig_stream_service.disconnect()
90 |
91 |
92 | if __name__ == "__main__":
93 | main()
94 |
--------------------------------------------------------------------------------
/sample/stream_stock_list_demo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | # Copyright 2015 Weswit s.r.l.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | import sys
18 | import traceback
19 | import logging
20 | from trading_ig.lightstreamer import LSClient, Subscription
21 |
22 |
23 | # A simple function acting as a Subscription listener
24 | def on_item_update(item_update):
25 | print(
26 | "{stock_name:<19}: Last{last_price:>6} - Time {time:<8} - "
27 | "Bid {bid:>5} - Ask {ask:>5}".format(**item_update["values"])
28 | )
29 |
30 |
31 | def main():
32 | # logging.basicConfig(level=logging.DEBUG)
33 | logging.basicConfig(level=logging.INFO)
34 |
35 | # Establishing a new connection to Lightstreamer Server
36 | print("Starting connection")
37 | # lightstreamer_client = LSClient("http://localhost:8080", "DEMO")
38 | lightstreamer_client = LSClient("http://push.lightstreamer.com", "DEMO")
39 | try:
40 | lightstreamer_client.connect()
41 | except Exception as e:
42 | print("Unable to connect to Lightstreamer Server")
43 | print(traceback.format_exc())
44 | print(e)
45 | sys.exit(1)
46 |
47 | # Making a new Subscription in MERGE mode
48 | subscription = Subscription(
49 | mode="MERGE",
50 | items=[
51 | "item1",
52 | "item2",
53 | "item3",
54 | "item4",
55 | "item5",
56 | "item6",
57 | "item7",
58 | "item8",
59 | "item9",
60 | "item10",
61 | "item11",
62 | "item12",
63 | ],
64 | fields=["stock_name", "last_price", "time", "bid", "ask"],
65 | adapter="QUOTE_ADAPTER",
66 | )
67 |
68 | # Adding the "on_item_update" function to Subscription
69 | subscription.addlistener(on_item_update)
70 |
71 | # Registering the Subscription
72 | sub_key = lightstreamer_client.subscribe(subscription)
73 | print(sub_key)
74 |
75 | input(
76 | "{0:-^80}\n".format(
77 | "HIT CR TO UNSUBSCRIBE AND DISCONNECT FROM \
78 | LIGHTSTREAMER"
79 | )
80 | )
81 |
82 | # Unsubscribing from Lightstreamer by using the subscription key
83 | # lightstreamer_client.unsubscribe(sub_key)
84 |
85 | lightstreamer_client.unsubscribe()
86 |
87 | # Disconnecting
88 | lightstreamer_client.disconnect()
89 |
90 |
91 | if __name__ == "__main__":
92 | main()
93 |
--------------------------------------------------------------------------------
/sample/rest_ig.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | """
5 | IG Markets REST API sample with Python
6 | 2015 FemtoTrader
7 | """
8 |
9 | from trading_ig import IGService
10 | from trading_ig.config import config
11 | import logging
12 |
13 | logger = logging.getLogger(__name__)
14 | logger.setLevel(logging.DEBUG)
15 |
16 | # if you need to cache to DB your requests
17 | from datetime import timedelta
18 | import requests_cache
19 |
20 |
21 | def main():
22 | logging.basicConfig(level=logging.DEBUG)
23 |
24 | expire_after = timedelta(hours=1)
25 | session = requests_cache.CachedSession(
26 | cache_name="cache", backend="sqlite", expire_after=expire_after
27 | )
28 | # set expire_after=None if you don't want cache expiration
29 | # set expire_after=0 if you don't want to cache queries
30 |
31 | # config = IGServiceConfig()
32 |
33 | # no cache
34 | ig_service = IGService(
35 | config.username, config.password, config.api_key, config.acc_type
36 | )
37 |
38 | # if you want to globally cache queries
39 | # ig_service = IGService(config.username, config.password, config.api_key, config.acc_type, session)
40 |
41 | ig_service.create_session()
42 |
43 | # accounts = ig_service.fetch_accounts()
44 | # print("accounts:\n%s" % accounts)
45 |
46 | # account_info = ig_service.switch_account(config.acc_number, False)
47 | # print(account_info)
48 |
49 | # open_positions = ig_service.fetch_open_positions()
50 | # print("open_positions:\n%s" % open_positions)
51 |
52 | print("")
53 |
54 | # working_orders = ig_service.fetch_working_orders()
55 | # print("working_orders:\n%s" % working_orders)
56 |
57 | print("")
58 |
59 | # epic = 'CS.D.EURUSD.MINI.IP'
60 | epic = "IX.D.ASX.IFM.IP" # US (SPY) - mini
61 |
62 | resolution = "D"
63 | # see from pandas.tseries.frequencies import to_offset
64 | # resolution = 'H'
65 | # resolution = '1Min'
66 |
67 | num_points = 10
68 | response = ig_service.fetch_historical_prices_by_epic_and_num_points(
69 | epic, resolution, num_points
70 | )
71 |
72 | print(response)
73 |
74 | # Exception: error.public-api.exceeded-account-historical-data-allowance
75 |
76 | # if you want to cache this query
77 | # response = ig_service.fetch_historical_prices_by_epic_and_num_points(epic, resolution, num_points, session)
78 |
79 | # df_ask = response['prices']['ask']
80 | # print("ask prices:\n%s" % df_ask)
81 |
82 | # (start_date, end_date) = ('2015-09-15', '2015-09-28')
83 | # response = ig_service.fetch_historical_prices_by_epic_and_date_range(epic, resolution, start_date, end_date)
84 |
85 | # if you want to cache this query
86 | # response = ig_service.fetch_historical_prices_by_epic_and_date_range(epic, resolution, start_date, end_date, session)
87 | # df_ask = response['prices']['ask']
88 | # print("ask prices:\n%s" % df_ask)
89 |
90 |
91 | if __name__ == "__main__":
92 | main()
93 |
--------------------------------------------------------------------------------
/getting_realtime_data/stream_ig_getting_realtime_data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #-*- coding:utf-8 -*-
3 |
4 | """
5 | IG Markets Stream API sample with Python
6 | 2015 FemtoTrader
7 | """
8 |
9 | import time
10 | import sys
11 | import traceback
12 | import logging
13 |
14 | from trading_ig import (IGService, IGStreamService)
15 | from trading_ig.config import config
16 | from trading_ig.lightstreamer import Subscription
17 |
18 |
19 | # A simple function acting as a Subscription listener
20 | def on_prices_update(item_update):
21 | # print("price: %s " % item_update)
22 | print("{stock_name:<19}: Time {UPDATE_TIME:<8} - "
23 | "Bid {BID:>5} - Ask {OFFER:>5}".format(
24 | stock_name=item_update["name"], **item_update["values"]
25 | ))
26 |
27 |
28 | def on_account_update(balance_update):
29 | print("balance: %s " % balance_update)
30 |
31 |
32 | def main():
33 | logging.basicConfig(level=logging.INFO)
34 | # logging.basicConfig(level=logging.DEBUG)
35 |
36 | ig_service = IGService(
37 | config.username, config.password, config.api_key, config.acc_type
38 | )
39 |
40 | ig_stream_service = IGStreamService(ig_service)
41 | ig_session = ig_stream_service.create_session()
42 | accountId = config.acc_number
43 | # Ensure configured account is selected
44 | # accounts = ig_session[u'accounts']
45 | # for account in accounts:
46 | # if account[u'accountId'] == config.acc_number:
47 | # accountId = account[u'accountId']
48 | # break
49 | # else:
50 | # print('Account not found: {0}'.format(config.acc_number))
51 | # accountId = None
52 | ig_stream_service.connect(accountId)
53 |
54 | # Making a new Subscription in MERGE mode
55 | subscription_prices = Subscription(
56 | mode="MERGE",
57 | # make sure to put L1 in front of the instrument name
58 | items=["L1:CS.D.BITCOIN.TODAY.IP", "L1:CS.D.ETHUSD.TODAY.IP"],
59 | fields=["UPDATE_TIME", "BID", "OFFER", "CHANGE", "MARKET_STATE", "MID_OPEN", "HIGH", "LOW", "CHANGE", "CHANGE_PCT", "MARKET_DELAY"]
60 | )
61 | # adapter="QUOTE_ADAPTER")
62 |
63 | # Adding the "on_price_update" function to Subscription
64 | subscription_prices.addlistener(on_prices_update)
65 |
66 | # Registering the Subscription
67 | sub_key_prices = ig_stream_service.ls_client.subscribe(subscription_prices)
68 |
69 | # Making an other Subscription in MERGE mode
70 | subscription_account = Subscription(
71 | mode="MERGE",
72 | items=['ACCOUNT:'+accountId],
73 | fields=["AVAILABLE_CASH"],
74 | )
75 | # #adapter="QUOTE_ADAPTER")
76 |
77 | # Adding the "on_balance_update" function to Subscription
78 | subscription_account.addlistener(on_account_update)
79 |
80 |
81 | # Registering the Subscription
82 | sub_key_account = ig_stream_service.ls_client.subscribe(
83 | subscription_account
84 | )
85 |
86 | input("{0:-^80}\n".format("HIT CR TO UNSUBSCRIBE AND DISCONNECT FROM \
87 | LIGHTSTREAMER"))
88 |
89 | # Disconnecting
90 | ig_stream_service.disconnect()
91 |
92 |
93 | if __name__ == '__main__':
94 | main()
95 |
--------------------------------------------------------------------------------
/trading_ig/utils.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | import os
5 | import logging
6 | import traceback
7 | import six
8 |
9 | logger = logging.getLogger(__name__)
10 |
11 | try:
12 | import pandas as pd
13 | except ImportError:
14 | _HAS_PANDAS = False
15 | logger.info("Can't import pandas")
16 | else:
17 | _HAS_PANDAS = True
18 |
19 | try:
20 | from munch import munchify # noqa
21 | except ImportError:
22 | _HAS_MUNCH = False
23 | logger.info("Can't import munch")
24 | else:
25 | _HAS_MUNCH = True
26 |
27 |
28 | DATE_FORMATS = {1: "%Y:%m:%d-%H:%M:%S", 2: "%Y/%m/%d %H:%M:%S", 3: "%Y/%m/%d %H:%M:%S"}
29 |
30 |
31 | def conv_resol(resolution):
32 | """Returns a string for resolution (from a Pandas)
33 | """
34 | if _HAS_PANDAS:
35 | from pandas.tseries.frequencies import to_offset
36 |
37 | d = {
38 | to_offset("1s"): "SECOND",
39 | to_offset("1Min"): "MINUTE",
40 | to_offset("2Min"): "MINUTE_2",
41 | to_offset("3Min"): "MINUTE_3",
42 | to_offset("5Min"): "MINUTE_5",
43 | to_offset("10Min"): "MINUTE_10",
44 | to_offset("15Min"): "MINUTE_15",
45 | to_offset("30Min"): "MINUTE_30",
46 | to_offset("1H"): "HOUR",
47 | to_offset("2H"): "HOUR_2",
48 | to_offset("3H"): "HOUR_3",
49 | to_offset("4H"): "HOUR_4",
50 | to_offset("D"): "DAY",
51 | to_offset("W"): "WEEK",
52 | to_offset("M"): "MONTH",
53 | }
54 | offset = to_offset(resolution)
55 | if offset in d:
56 | return d[offset]
57 | else:
58 | logger.error(traceback.format_exc())
59 | logger.warning("conv_resol returns '%s'" % resolution)
60 | return resolution
61 | else:
62 | return resolution
63 |
64 |
65 | def conv_datetime(dt, version=2):
66 | """Converts dt to string like
67 | version 1 = 2014:12:15-00:00:00
68 | version 2 = 2014/12/15 00:00:00
69 | version 3 = 2014/12/15 00:00:00
70 | """
71 | try:
72 | if isinstance(dt, six.string_types):
73 | if _HAS_PANDAS:
74 | dt = pd.to_datetime(dt)
75 |
76 | fmt = DATE_FORMATS[int(version)]
77 | return dt.strftime(fmt)
78 | except (ValueError, TypeError):
79 | logger.error(traceback.format_exc())
80 | logger.warning("conv_datetime returns %s" % dt)
81 | return dt
82 |
83 |
84 | def conv_to_ms(td):
85 | """Converts td to integer number of milliseconds"""
86 | try:
87 | if isinstance(td, six.integer_types):
88 | return td
89 | else:
90 | return int(td.total_seconds() * 1000.0)
91 | except ValueError:
92 | logger.error(traceback.format_exc())
93 | logger.warning("conv_to_ms returns '%s'" % td)
94 | return td
95 |
96 |
97 | def remove(cache):
98 | """Remove cache"""
99 | try:
100 | filename = "%s.sqlite" % cache
101 | print("remove %s" % filename)
102 | os.remove(filename)
103 | except Exception:
104 | pass
105 |
--------------------------------------------------------------------------------
/tests/data/historic_prices_v1.json:
--------------------------------------------------------------------------------
1 | {
2 | "prices": [
3 | {
4 | "snapshotTime": "2020:09:01-05:00:00",
5 | "openPrice": {
6 | "bid": 1992.7,
7 | "ask": 1993.3,
8 | "lastTraded": null
9 | },
10 | "closePrice": {
11 | "bid": 1970.7,
12 | "ask": 1971.3,
13 | "lastTraded": null
14 | },
15 | "highPrice": {
16 | "bid": 2000.4,
17 | "ask": 2001.0,
18 | "lastTraded": null
19 | },
20 | "lowPrice": {
21 | "bid": 1965.5,
22 | "ask": 1966.1,
23 | "lastTraded": null
24 | },
25 | "lastTradedVolume": 202326
26 | },
27 | {
28 | "snapshotTime": "2020:09:02-05:00:00",
29 | "openPrice": {
30 | "bid": 1970.8,
31 | "ask": 1971.4,
32 | "lastTraded": null
33 | },
34 | "closePrice": {
35 | "bid": 1951.3,
36 | "ask": 1951.9,
37 | "lastTraded": null
38 | },
39 | "highPrice": {
40 | "bid": 1978.4,
41 | "ask": 1979.0,
42 | "lastTraded": null
43 | },
44 | "lowPrice": {
45 | "bid": 1938.7,
46 | "ask": 1939.3,
47 | "lastTraded": null
48 | },
49 | "lastTradedVolume": 214134
50 | },
51 | {
52 | "snapshotTime": "2020:09:03-05:00:00",
53 | "openPrice": {
54 | "bid": 1951.4,
55 | "ask": 1952.0,
56 | "lastTraded": null
57 | },
58 | "closePrice": {
59 | "bid": 1942.8,
60 | "ask": 1943.4,
61 | "lastTraded": null
62 | },
63 | "highPrice": {
64 | "bid": 1952.5,
65 | "ask": 1953.1,
66 | "lastTraded": null
67 | },
68 | "lowPrice": {
69 | "bid": 1927.0,
70 | "ask": 1927.6,
71 | "lastTraded": null
72 | },
73 | "lastTradedVolume": 215716
74 | },
75 | {
76 | "snapshotTime": "2020:09:04-05:00:00",
77 | "openPrice": {
78 | "bid": 1942.9,
79 | "ask": 1943.5,
80 | "lastTraded": null
81 | },
82 | "closePrice": {
83 | "bid": 1940.9,
84 | "ask": 1940.9,
85 | "lastTraded": null
86 | },
87 | "highPrice": {
88 | "bid": 1955.2,
89 | "ask": 1956.2,
90 | "lastTraded": null
91 | },
92 | "lowPrice": {
93 | "bid": 1921.7,
94 | "ask": 1922.3,
95 | "lastTraded": null
96 | },
97 | "lastTradedVolume": 167178
98 | }
99 | ],
100 | "instrumentType": "COMMODITIES",
101 | "allowance": {
102 | "remainingAllowance": 9986,
103 | "totalAllowance": 10000,
104 | "allowanceExpiry": 462679
105 | }
106 | }
--------------------------------------------------------------------------------
/getting_instrument_based_data/update_instrument_data_IG.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | from trading_ig import IGService
5 | from trading_ig.config import config
6 |
7 | from datetime import timedelta
8 | import requests_cache
9 | import json
10 | import pandas as pd
11 | pd.options.mode.chained_assignment = None # default='warn'
12 |
13 |
14 | def main():
15 | ig_service = login()
16 |
17 | get_data(ig_service)
18 |
19 | def login():
20 | expire_after = timedelta(hours=1)
21 | session = requests_cache.CachedSession(
22 | cache_name='cache', backend='sqlite', expire_after=expire_after
23 | )
24 | api_key = increment_api_key()
25 |
26 | # no cache
27 | ig_service = IGService(
28 | config.username, config.password, api_key, config.acc_type
29 | )
30 | ig_service.create_session()
31 |
32 | return ig_service
33 |
34 |
35 |
36 | def get_data(ig_service):
37 | Instrument_Data = pd.read_csv("D:\Stock_Analysis\ig-markets-api-python-library-master\Data\SpreadBetting\instruments_new.csv")
38 | Instrument_Data.drop("Unnamed: 0", axis=1, inplace=True)
39 |
40 | for index in range(Instrument_Data.index.size):
41 | # save the data
42 | try:
43 | data = get_data_required(Instrument_Data, index, ig_service)
44 | # if data == None:
45 | # continue
46 | temp = data["instrument"].copy()
47 | temp.update(data["dealingRules"])
48 | temp.update(data["snapshot"])
49 |
50 | data = temp
51 | put_in_right_column(data=data, Instrument_Data=Instrument_Data, index=index)
52 |
53 | Instrument_Data.to_csv("D:\Stock_Analysis\ig-markets-api-python-library-master\Data\SpreadBetting\instruments_new_updated.csv")
54 |
55 | except Exception as e:
56 | print(e)
57 |
58 |
59 | print("finished")
60 |
61 |
62 | def get_data_required(Instrument_Data, index, ig_service):
63 | try:
64 | row = Instrument_Data.iloc[index]
65 | epic_id = row["epic"]
66 | # save data
67 | map_data = get_details_about_epic(ig_service, epic_id)
68 | data_string = json.dumps(map_data)
69 | data = json.loads(data_string)
70 | return data
71 | except Exception as e:
72 | print(e)
73 | return None
74 |
75 |
76 | def put_in_right_column(data, Instrument_Data, index):
77 | object_df = Instrument_Data.loc[index]
78 | for key in data.keys():
79 | object_df[key] = data[key]
80 | Instrument_Data.loc[index] = object_df
81 | print("stop")
82 |
83 |
84 | def get_details_about_epic(ig_service, epic):
85 | while(True):
86 | try:
87 | map_of_data = ig_service.fetch_market_by_epic(epic)
88 | return map_of_data
89 | except Exception as e:
90 | print(e)
91 | login()
92 |
93 |
94 | def increment_api_key():
95 | key = ""
96 | global counter
97 | flag = True
98 | while (flag):
99 | try:
100 | counter += 1
101 | fp = open("D:\Stock_Analysis\ig-markets-api-python-library-master\generate_api_keys\IG_api_keys_raw.txt")
102 | for i, line in enumerate(fp):
103 | if i == counter:
104 | key = line.split("\n")[0]
105 | flag = False
106 | break
107 |
108 | fp.close()
109 | except:
110 | counter = -1
111 |
112 | return key
113 |
114 |
115 |
116 |
117 | if __name__ == '__main__':
118 | main()
119 |
--------------------------------------------------------------------------------
/tests/data/historic_prices_dates.json:
--------------------------------------------------------------------------------
1 | {
2 | "prices": [
3 | {
4 | "snapshotTime": "2020/09/01 05:00:00",
5 | "snapshotTimeUTC": "2020-09-01T04:00:00",
6 | "openPrice": {
7 | "bid": 1992.7,
8 | "ask": 1993.3,
9 | "lastTraded": null
10 | },
11 | "closePrice": {
12 | "bid": 1970.7,
13 | "ask": 1971.3,
14 | "lastTraded": null
15 | },
16 | "highPrice": {
17 | "bid": 2000.4,
18 | "ask": 2001.0,
19 | "lastTraded": null
20 | },
21 | "lowPrice": {
22 | "bid": 1965.5,
23 | "ask": 1966.1,
24 | "lastTraded": null
25 | },
26 | "lastTradedVolume": 202326
27 | },
28 | {
29 | "snapshotTime": "2020/09/02 05:00:00",
30 | "snapshotTimeUTC": "2020-09-02T04:00:00",
31 | "openPrice": {
32 | "bid": 1970.8,
33 | "ask": 1971.4,
34 | "lastTraded": null
35 | },
36 | "closePrice": {
37 | "bid": 1951.3,
38 | "ask": 1951.9,
39 | "lastTraded": null
40 | },
41 | "highPrice": {
42 | "bid": 1978.4,
43 | "ask": 1979.0,
44 | "lastTraded": null
45 | },
46 | "lowPrice": {
47 | "bid": 1938.7,
48 | "ask": 1939.3,
49 | "lastTraded": null
50 | },
51 | "lastTradedVolume": 214134
52 | },
53 | {
54 | "snapshotTime": "2020/09/03 05:00:00",
55 | "snapshotTimeUTC": "2020-09-03T04:00:00",
56 | "openPrice": {
57 | "bid": 1951.4,
58 | "ask": 1952.0,
59 | "lastTraded": null
60 | },
61 | "closePrice": {
62 | "bid": 1942.8,
63 | "ask": 1943.4,
64 | "lastTraded": null
65 | },
66 | "highPrice": {
67 | "bid": 1952.5,
68 | "ask": 1953.1,
69 | "lastTraded": null
70 | },
71 | "lowPrice": {
72 | "bid": 1927.0,
73 | "ask": 1927.6,
74 | "lastTraded": null
75 | },
76 | "lastTradedVolume": 215716
77 | },
78 | {
79 | "snapshotTime": "2020/09/04 05:00:00",
80 | "snapshotTimeUTC": "2020-09-04T04:00:00",
81 | "openPrice": {
82 | "bid": 1942.9,
83 | "ask": 1943.5,
84 | "lastTraded": null
85 | },
86 | "closePrice": {
87 | "bid": 1940.9,
88 | "ask": 1940.9,
89 | "lastTraded": null
90 | },
91 | "highPrice": {
92 | "bid": 1955.2,
93 | "ask": 1956.2,
94 | "lastTraded": null
95 | },
96 | "lowPrice": {
97 | "bid": 1921.7,
98 | "ask": 1922.3,
99 | "lastTraded": null
100 | },
101 | "lastTradedVolume": 167178
102 | }
103 | ],
104 | "instrumentType": "COMMODITIES",
105 | "metadata": {
106 | "allowance": {
107 | "remainingAllowance": 500,
108 | "totalAllowance": 10000,
109 | "allowanceExpiry": 50000
110 | },
111 | "size": 4,
112 | "pageData": {
113 | "pageSize": 20,
114 | "pageNumber": 1,
115 | "totalPages": 1
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/predefined_functions/algo_creating_working_orders_at_open_on_both_side_quick_functions.py:
--------------------------------------------------------------------------------
1 | from trading_ig.config import config
2 | import logging
3 |
4 | logger = logging.getLogger(__name__)
5 | logger.setLevel(logging.DEBUG)
6 |
7 | # if you need to cache to DB your requests
8 | from datetime import timedelta
9 | import requests_cache
10 | from getting_realtime_data.data_retrieval import Data_Retrieval
11 | from sending_orders.order_management import Order_Management
12 | from management_of_position.position_management import Position_Management
13 | from predefined_functions.initialisation import Initialisation
14 | from get_data.get_market_data import Get_Market_Data
15 | import time
16 | from datetime import datetime, timedelta, date
17 | from predefined_functions.defined_functionality import Defined_Functionality
18 | import traceback
19 | import pandas as pd
20 | import sys
21 | import math
22 |
23 | # the newest one where you make market order base on price movements 5 or more and try to catch the trend
24 |
25 | class Algo0:
26 | def __init__(self):
27 | logging.basicConfig(level=logging.INFO)
28 | self.df = Defined_Functionality()
29 |
30 |
31 |
32 |
33 | def run(self):
34 |
35 | while(True):
36 |
37 | try:
38 |
39 | start_time = datetime.now()
40 | self.check_all_working_orders()
41 | end_time = datetime.now() - start_time
42 | print(end_time)
43 |
44 | except Exception as e:
45 | print(e, "traceback back in custom algo frame work")
46 | traceback.print_exc()
47 |
48 | def check_all_working_orders(self):
49 | # check if opening market has passed , if we have a position in it then close all other orders, or if only one of that order remains
50 | orders = self.df.get_working_orders()
51 | for epic in orders["epic"].unique():
52 | self.checking_working_order_is_present_under_epic_and_amend_orders(epic=epic)
53 |
54 |
55 |
56 | def checking_working_order_is_present_under_epic_and_amend_orders(self, epic):
57 | # check there are two orders for each epic
58 | created_order = True
59 | while(True):
60 | orders = self.df.get_working_orders_by_epic(epic=epic)
61 | if orders.index.size == 2:
62 | directions = orders["direction"].to_list()
63 | if ("BUY" in directions and "SELL" in directions):
64 | data = self.df.get_market_data(epic=epic)
65 |
66 | if data == None:
67 | continue
68 | # market is still open
69 | map_of_time = data["instrument"]["openingHours"]
70 | if map_of_time == None:
71 | break
72 | single_time = map_of_time["marketTimes"][0]["openTime"]
73 | opening_market_time = datetime.strptime(single_time, '%H:%M').time()
74 | diff_in_time = datetime.combine(date.today(), opening_market_time) - datetime.now()
75 |
76 | # if the time is bigger than x second then we can still put orders in place
77 | total_seconds = diff_in_time.total_seconds()
78 | # -1 seconds
79 | if total_seconds < -(0.2):
80 | # delete the orders if any are pending
81 | break
82 |
83 | position = self.df.find_open_position_by_epic(epic=epic)
84 | if len(position) != 0:
85 | break
86 |
87 | print("market is not open yet and orders are in place nothing needs to be done yet")
88 | return created_order
89 |
90 | break
91 |
92 | print("delete orders")
93 | self.df.cancel_orders_by_epic(epic=epic)
94 | created_order = False
95 |
96 | return created_order
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Always prefer setuptools over distutils
5 | from setuptools import setup, find_packages
6 | from codecs import open # To use a consistent encoding
7 | from os import path
8 | import io
9 |
10 | NAME = "trading_ig"
11 | filename = "%s/version.py" % NAME
12 | with open(filename) as f:
13 | exec(f.read())
14 |
15 | here = path.abspath(path.dirname(__file__))
16 |
17 |
18 | def readme():
19 | filename = path.join(here, "README.rst")
20 | with io.open(filename, "rt", encoding="UTF-8") as f:
21 | return f.read()
22 |
23 |
24 | setup(
25 | name=NAME,
26 | # Versions should comply with PEP440. For a discussion on single-sourcing
27 | # the version across setup.py and the project code, see
28 | # https://packaging.python.org/en/latest/development.html#single-sourcing-the-version
29 | # version='0.0.1',
30 | version=__version__,
31 | description="A lightweight wrapper for the IG Markets API written in Python",
32 | long_description=readme(),
33 | # The project's main homepage.
34 | url=__url__,
35 | # Author details
36 | author=__author__,
37 | author_email=__author_email__,
38 | # Choose your license
39 | license=__license__,
40 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
41 | classifiers=[
42 | # How mature is this project? Common values are
43 | # 3 - Alpha
44 | # 4 - Beta
45 | # 5 - Production/Stable
46 | "Development Status :: 3 - Alpha",
47 | # Indicate who your project is intended for
48 | "Environment :: Console",
49 | # 'Topic :: Software Development :: Build Tools',
50 | "Intended Audience :: Science/Research",
51 | "Operating System :: OS Independent",
52 | # Specify the Python versions you support here. In particular, ensure
53 | # that you indicate whether you support Python 2, Python 3 or both.
54 | "Programming Language :: Cython",
55 | "Programming Language :: Python",
56 | "Programming Language :: Python :: 3.6",
57 | "Programming Language :: Python :: 3.7",
58 | "Programming Language :: Python :: 3.8",
59 | "Topic :: Scientific/Engineering",
60 | # Pick your license as you wish (should match "license" above)
61 | "License :: OSI Approved :: BSD License",
62 | ],
63 | python_requires='>=3.6',
64 | # What does your project relate to?
65 | keywords="trading, spread betting, CFDs",
66 | # You can just specify the packages manually here if your project is
67 | # simple. Or you can use find_packages().
68 | packages=find_packages(exclude=["contrib", "docs", "tests*"]),
69 | # List run-time dependencies here. These will be installed by pip when your
70 | # project is installed. For an analysis of "install_requires" vs pip's
71 | # requirements files see:
72 | # https://packaging.python.org/en/latest/technical.html#install-requires-vs-requirements-files
73 | install_requires=[
74 | "munch==2.5.0",
75 | "pycryptodome==3.9.8",
76 | "requests==2.24.0",
77 | "requests-cache==0.5.2",
78 | "six==1.15.0",
79 | "pandas==1.0.5",
80 | ], # bunch->lunch->infi.bunch->munch
81 | # List additional groups of dependencies here (e.g. development dependencies).
82 | # You can install these using the following syntax, for example:
83 | # $ pip install -e .[dev,test]
84 | extras_require={"dev": ["check-manifest", "pytest"], "test": ["pytest", "pytest-cov"],},
85 | # If there are data files included in your packages that need to be
86 | # installed, specify them here. If using Python 2.6 or less, then these
87 | # have to be included in MANIFEST.in as well.
88 | # package_data={
89 | # 'sample': ['logging.conf'],
90 | # },
91 | # Although 'package_data' is the preferred approach, in some case you may
92 | # need to place data files outside of your packages.
93 | # see http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files
94 | # In this case, 'data_file' will be installed into '/my_data'
95 | # data_files=[('my_data', ['data/data_file'])],
96 | # To provide executable scripts, use entry points in preference to the
97 | # "scripts" keyword. Entry points provide cross-platform support and allow
98 | # pip to create the appropriate form of executable for the target platform.
99 | entry_points={"console_scripts": ["sample=sample:main",],},
100 | )
101 |
--------------------------------------------------------------------------------
/tests/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Always prefer setuptools over distutils
5 | from setuptools import setup, find_packages
6 | from codecs import open # To use a consistent encoding
7 | from os import path
8 | import io
9 |
10 | NAME = "trading_ig"
11 | filename = "%s/version.py" % NAME
12 | with open(filename) as f:
13 | exec(f.read())
14 |
15 | here = path.abspath(path.dirname(__file__))
16 |
17 |
18 | def readme():
19 | filename = path.join(here, "README.rst")
20 | with io.open(filename, "rt", encoding="UTF-8") as f:
21 | return f.read()
22 |
23 |
24 | setup(
25 | name=NAME,
26 | # Versions should comply with PEP440. For a discussion on single-sourcing
27 | # the version across setup.py and the project code, see
28 | # https://packaging.python.org/en/latest/development.html#single-sourcing-the-version
29 | # version='0.0.1',
30 | version=__version__,
31 | description="A lightweight wrapper for the IG Markets API written in Python",
32 | long_description=readme(),
33 | # The project's main homepage.
34 | url=__url__,
35 | # Author details
36 | author=__author__,
37 | author_email=__author_email__,
38 | # Choose your license
39 | license=__license__,
40 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
41 | classifiers=[
42 | # How mature is this project? Common values are
43 | # 3 - Alpha
44 | # 4 - Beta
45 | # 5 - Production/Stable
46 | "Development Status :: 3 - Alpha",
47 | # Indicate who your project is intended for
48 | "Environment :: Console",
49 | # 'Topic :: Software Development :: Build Tools',
50 | "Intended Audience :: Science/Research",
51 | "Operating System :: OS Independent",
52 | # Specify the Python versions you support here. In particular, ensure
53 | # that you indicate whether you support Python 2, Python 3 or both.
54 | "Programming Language :: Cython",
55 | "Programming Language :: Python",
56 | "Programming Language :: Python :: 3.6",
57 | "Programming Language :: Python :: 3.7",
58 | "Programming Language :: Python :: 3.8",
59 | "Topic :: Scientific/Engineering",
60 | # Pick your license as you wish (should match "license" above)
61 | "License :: OSI Approved :: BSD License",
62 | ],
63 | python_requires='>=3.6',
64 | # What does your project relate to?
65 | keywords="trading, spread betting, CFDs",
66 | # You can just specify the packages manually here if your project is
67 | # simple. Or you can use find_packages().
68 | packages=find_packages(exclude=["contrib", "docs", "tests*"]),
69 | # List run-time dependencies here. These will be installed by pip when your
70 | # project is installed. For an analysis of "install_requires" vs pip's
71 | # requirements files see:
72 | # https://packaging.python.org/en/latest/technical.html#install-requires-vs-requirements-files
73 | install_requires=[
74 | "munch==2.5.0",
75 | "pycryptodome==3.9.8",
76 | "requests==2.24.0",
77 | "requests-cache==0.5.2",
78 | "six==1.15.0",
79 | "pandas==1.0.5",
80 | ], # bunch->lunch->infi.bunch->munch
81 | # List additional groups of dependencies here (e.g. development dependencies).
82 | # You can install these using the following syntax, for example:
83 | # $ pip install -e .[dev,test]
84 | extras_require={"dev": ["check-manifest", "pytest"], "test": ["pytest", "pytest-cov"],},
85 | # If there are data files included in your packages that need to be
86 | # installed, specify them here. If using Python 2.6 or less, then these
87 | # have to be included in MANIFEST.in as well.
88 | # package_data={
89 | # 'sample': ['logging.conf'],
90 | # },
91 | # Although 'package_data' is the preferred approach, in some case you may
92 | # need to place data files outside of your packages.
93 | # see http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files
94 | # In this case, 'data_file' will be installed into '/my_data'
95 | # data_files=[('my_data', ['data/data_file'])],
96 | # To provide executable scripts, use entry points in preference to the
97 | # "scripts" keyword. Entry points provide cross-platform support and allow
98 | # pip to create the appropriate form of executable for the target platform.
99 | entry_points={"console_scripts": ["sample=sample:main",],},
100 | )
101 |
--------------------------------------------------------------------------------
/predefined_functions/temp_algo_tut.py:
--------------------------------------------------------------------------------
1 | from predefined_functions.defined_functionality import Defined_Functionality
2 | from datetime import datetime
3 | import pandas as pd
4 |
5 | class Algo0:
6 | def __init__(self):
7 | self.df = Defined_Functionality()
8 |
9 | self.list_of_epics = ['IX.D.DOW.DAILY.IP']
10 | self.df.set_epics_to_look_for(epic_list=self.list_of_epics)
11 |
12 | self.map_epic_data_minute={}
13 | for epic in self.list_of_epics:
14 | self.map_epic_data_minute[epic] = []
15 |
16 | self.first_timestamp = None
17 |
18 |
19 |
20 | def run(self):
21 |
22 | while(True):
23 | try:
24 | epic = self.list_of_epics[0]
25 | signals = self.signal_generation(epic)
26 | self.create_positions(epic=epic, signals_levels=signals)
27 | self.closing_positions(epic=epic, signals= signals)
28 |
29 | except Exception as e:
30 | print(e, " error in the looping for the defined_functionality")
31 |
32 | def closing_positions(self, epic, signals):
33 | position = self.df.find_open_position_by_epic(epic=epic)
34 |
35 | if len(position) == 0:
36 | return
37 |
38 | if isinstance(position[0],pd.core.series.Series):
39 | if signals == None:
40 | return
41 |
42 | if (signals["BUY"] != None and (position[0]["position"]["direction"] != "BUY")):
43 | self.df.close_position(position=position[0])
44 |
45 | elif (signals["SELL"] != None and (position[0]["position"]["direction"] != "SELL")):
46 | self.df.close_position(position=position[0])
47 |
48 | def create_positions(self, epic, signals_levels):
49 | if signals_levels == None:
50 | return
51 | key = None
52 | if signals_levels["BUY"] != None:
53 | key = "BUY"
54 | elif signals_levels["SELL"] != None:
55 | key = "SELL"
56 |
57 |
58 | position = self.df.find_open_position_by_epic(epic=epic)
59 |
60 | if len(position) != 0:
61 | return position
62 |
63 |
64 | create_position = self.df.create_open_position(epic=epic, direction=key, size=0.5)
65 |
66 | return create_position
67 |
68 |
69 | def signal_generation(self, epic):
70 | signals_levels = None
71 | # minute_10 = 60 * 10
72 | # minute_10 = 60
73 | minute_10 = 1
74 | datetime_now = datetime.now()
75 | data = None
76 |
77 | if (self.first_timestamp != None):
78 | difference = (datetime_now - self.first_timestamp)
79 |
80 | if (difference.seconds > minute_10):
81 | data = self.df.get_market_data(epic=epic)
82 | self.first_timestamp = datetime_now
83 | self.map_epic_data_minute[epic].append(data)
84 |
85 | else:
86 | data = self.df.get_market_data(epic=epic)
87 | self.first_timestamp = datetime_now
88 |
89 | self.map_epic_data_minute[epic].append(data)
90 | # self.finding_lows_highs(data=data)
91 |
92 | if len(self.map_epic_data_minute[epic]) > 3:
93 | self.map_epic_data_minute[epic].pop(0)
94 |
95 | sell_level = None
96 | buy_level = None
97 |
98 | object_epic_data = self.map_epic_data_minute[epic][-1]
99 | bid = object_epic_data["snapshot"]["bid"]
100 | offer = object_epic_data["snapshot"]["offer"]
101 | high = object_epic_data["snapshot"]["high"]
102 | low = object_epic_data["snapshot"]["low"]
103 |
104 | object_epic_data = self.map_epic_data_minute[epic][-2]
105 | bid_old = object_epic_data["snapshot"]["bid"]
106 | offer_old = object_epic_data["snapshot"]["offer"]
107 | high_old = object_epic_data["snapshot"]["high"]
108 | low_old = object_epic_data["snapshot"]["low"]
109 |
110 | offer_diff = offer - offer_old
111 | bid_diff = bid - bid_old
112 |
113 | # if offer_diff > 0.1:
114 | buy_level = 1
115 | # elif bid_diff < -0.1:
116 | sell_level = 1
117 |
118 |
119 | self.map_epic_data_minute[epic] = []
120 | # instead here we are using bid/offer
121 |
122 | if (sell_level == None) and (buy_level == None):
123 | return None
124 |
125 | signals_levels = {
126 | "SELL": sell_level,
127 | "BUY": buy_level
128 | }
129 |
130 | return signals_levels
131 |
132 |
133 |
--------------------------------------------------------------------------------
/sending_orders/rest_ig_sending_orders.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | """
5 | IG Markets REST API sample with Python
6 | 2015 FemtoTrader
7 | """
8 |
9 | from trading_ig import IGService
10 | from trading_ig.config import config
11 | import logging
12 |
13 | logger = logging.getLogger(__name__)
14 | logger.setLevel(logging.DEBUG)
15 |
16 | # if you need to cache to DB your requests
17 | from datetime import timedelta
18 | import requests_cache
19 |
20 |
21 | def main():
22 | logging.basicConfig(level=logging.DEBUG)
23 |
24 | expire_after = timedelta(hours=1)
25 | session = requests_cache.CachedSession(
26 | cache_name='cache', backend='sqlite', expire_after=expire_after
27 | )
28 | # set expire_after=None if you don't want cache expiration
29 | # set expire_after=0 if you don't want to cache queries
30 |
31 | #config = IGServiceConfig()
32 |
33 | # no cache
34 | ig_service = IGService(
35 | config.username, config.password, config.api_key, config.acc_type
36 | )
37 |
38 | # if you want to globally cache queries
39 | #ig_service = IGService(config.username, config.password, config.api_key, config.acc_type, session)
40 |
41 | ig_service.create_session()
42 |
43 | accounts = ig_service.fetch_accounts()
44 | print("accounts:\n%s" % accounts)
45 | """
46 | # - as it is set to default ift no longer needed gets the account to the spread betting one , the one specified in the config file
47 | ig_service.switch_account(account_id=config.acc_number, default_account=True)
48 | """
49 |
50 | #open_positions = ig_service.fetch_open_positions()
51 | #print("open_positions:\n%s" % open_positions)
52 |
53 | print("")
54 |
55 | working_orders = ig_service.fetch_working_orders()
56 | print("working_orders:\n%s" % working_orders)
57 |
58 | print("")
59 |
60 | currency_code = "GBP"
61 | direction = "BUY"
62 | epic = "IX.D.FTSE.DAILY.IP"
63 | expiry = "DFB"
64 | guaranteed_stop = False
65 | # entering price
66 | level = 6801.3
67 | # Pound per point size
68 | size = 1
69 | time_in_force = "GOOD_TILL_CANCELLED"
70 | # limit orders are now called STOP
71 | order_type = "STOP"
72 | limit_distance = None
73 | stop_distance = 160
74 |
75 | # """Creates an OTC working order"""
76 | response = ig_service.create_working_order(
77 | currency_code=currency_code,
78 | direction=direction,
79 | epic=epic,
80 | expiry=expiry,
81 | guaranteed_stop=guaranteed_stop,
82 | level=level,
83 | size=size,
84 | time_in_force=time_in_force,
85 | order_type=order_type,
86 | limit_distance=limit_distance,
87 | stop_distance=stop_distance
88 | )
89 |
90 | # ig_service.create_working_order(
91 | # currency_code="GBP",
92 | # direction="BUY",
93 | # epic="CS.D.BITCOIN.TODAY.IP",
94 | # expiry="DFB",
95 | # force_open=True,
96 | # guaranteed_stop=True,
97 | # stop_distance=1100.0,
98 | # size=0.50,
99 | # time_in_force="GOOD_TILL_CANCELLED",
100 | # order_type="LIMIT",
101 | # limit_distance=1000.0,
102 | # level=1000.0)
103 |
104 |
105 | print("")
106 |
107 | working_orders = ig_service.fetch_working_orders()
108 | print("working_orders:\n%s" % working_orders)
109 |
110 |
111 | # response is a dict -> response["price"] -> DataFrame (Multi-level df)-> so df = response["price"]
112 | # df -> df["ask"] -> Open,High,Low,Close
113 | # df -> df["bid"] -> Open,High,Low,Close
114 | # df -> df["last"] -> but these are usually None values = (Open,High,Low,Close)
115 | print(response)
116 | # Exception: error.public-api.exceeded-account-historical-data-allowance
117 |
118 | # if you want to cache this query
119 | #response = ig_service.fetch_historical_prices_by_epic_and_num_points(epic, resolution, num_points, session)
120 |
121 | #df_ask = response['prices']['ask']
122 | #print("ask prices:\n%s" % df_ask)
123 |
124 | #(start_date, end_date) = ('2015-09-15', '2015-09-28')
125 | #response = ig_service.fetch_historical_prices_by_epic_and_date_range(epic, resolution, start_date, end_date)
126 |
127 | # if you want to cache this query
128 | #response = ig_service.fetch_historical_prices_by_epic_and_date_range(epic, resolution, start_date, end_date, session)
129 | #df_ask = response['prices']['ask']
130 | #print("ask prices:\n%s" % df_ask)
131 |
132 |
133 |
134 | # check this out and see what you can do to get all the market data information
135 |
136 |
137 |
138 | if __name__ == '__main__':
139 | main()
140 |
--------------------------------------------------------------------------------
/Linked_to_biggest_previous_day_difference_in_price/adding_all_realtime_IG_data_to_file.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | """
5 | IG Markets REST API sample with Python
6 | 2015 FemtoTrader
7 | """
8 |
9 | from trading_ig import IGService
10 | from trading_ig.config import config
11 | import logging
12 | # format to
13 | # # from folder.file import class
14 | # from getting_instrument_based_data.navigate_tree import NavigateTree
15 |
16 | logger = logging.getLogger(__name__)
17 | logger.setLevel(logging.DEBUG)
18 |
19 | # if you need to cache to DB your requests
20 | from datetime import timedelta
21 | import requests_cache
22 | import time
23 | import os
24 | import json
25 | import pandas as pd
26 |
27 |
28 | counter = -1
29 | ig_service = None
30 |
31 |
32 |
33 | def login():
34 | expire_after = timedelta(hours=1)
35 | session = requests_cache.CachedSession(
36 | cache_name='cache', backend='sqlite', expire_after=expire_after
37 | )
38 | api_key = increment_api_key()
39 |
40 | global ig_service
41 |
42 | # no cache
43 | ig_service = IGService(
44 | config.username, config.password, api_key, config.acc_type
45 | )
46 | ig_service.create_session()
47 |
48 |
49 |
50 | def main():
51 |
52 | login()
53 |
54 | date = "2020-12-10_2021-02-10"
55 | # date = "2020-09-10_2020-12-10"
56 | time_interval = "5Min"
57 | get_data(date, time_interval)
58 |
59 |
60 |
61 | def get_data(date, time_interval):
62 |
63 | histroical_path_location = "D:\Data\IG_Instrument\historical_data\\" + time_interval + "\\" + date
64 |
65 |
66 | holding_list = []
67 |
68 | files = os.listdir(histroical_path_location)
69 |
70 | for f in files:
71 | # save the data
72 | try:
73 | name = f
74 | epic = name.split("_ID_")[1]
75 | data = get_details_about_epic(epic)
76 | # get the magin requirement from here ---------------------------------------------------------------------------------------------
77 | data = json.loads(json.dumps(data))
78 | #
79 | # map_of_items = {
80 | # "value" : data["instrument"]["marginFactor"],
81 | # "unit" : data["instrument"]["marginFactorUnit"]}
82 | #
83 | # difference_required = map_of_items["value"]
84 | # # otherwise the unit is POINTS
85 | # if map_of_items["unit"] == "PERCENTAGE":
86 | # difference_required = difference_required / 100
87 | #
88 | # difference_required * current_price
89 | temp = data["instrument"].copy()
90 | temp.update(data["dealingRules"])
91 | temp.update(data["snapshot"])
92 | temp["file_name"] = name
93 |
94 |
95 | whole_file_location = os.path.join(histroical_path_location, name)
96 | historical_data = pd.read_csv(whole_file_location, header=[0, 1], index_col=0)
97 | historical_data.index = pd.to_datetime(historical_data.index)
98 |
99 | bid = historical_data.iloc[0]["bid"]["Close"]
100 | ask = historical_data.iloc[0]["ask"]["Close"]
101 | spread = ask - bid
102 |
103 | temp["spread"] = spread
104 | temp["average"] = (bid + ask) / 2.0
105 | temp["diff_high-low"] = historical_data["bid"]["High"].max() - historical_data["bid"]["Low"].min()
106 | # could divide by zero and cause an error but would be caught by try and except clause
107 | temp["percent_spread-hl"] = (temp["spread"] / temp["diff_high-low"] * 100)
108 |
109 |
110 | holding_list.append(temp)
111 |
112 |
113 |
114 | except Exception as e:
115 | print(e)
116 | dataframe = pd.DataFrame(holding_list)
117 |
118 | dataframe.to_csv("D:\Stock_Analysis\IG_Data_Fixing\Results\All_instrument_data_added.csv")
119 |
120 | def get_details_about_epic(epic):
121 | global ig_service
122 | while(True):
123 | try:
124 | map_of_data = ig_service.fetch_market_by_epic(epic)
125 | return map_of_data
126 | except Exception as e:
127 | print(e)
128 | login()
129 |
130 |
131 | def increment_api_key():
132 | key = ""
133 | global counter
134 | flag = True
135 | while (flag):
136 | try:
137 | counter += 1
138 | # has 12000 api keys
139 | fp = open("D:\Stock_Analysis\ig-markets-api-python-library-master\generate_api_keys\IG_api_keys_raw.txt")
140 | for i, line in enumerate(fp):
141 | if i == counter:
142 | key = line.split("\n")[0]
143 | flag = False
144 | break
145 |
146 | fp.close()
147 | except:
148 | counter = -1
149 |
150 | return key
151 |
152 |
153 |
154 | if __name__ == '__main__':
155 | main()
156 |
--------------------------------------------------------------------------------
/getting_instrument_based_data/rest_ig_get_instrument_data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | import pandas as pd
5 |
6 | from trading_ig import IGService
7 | from trading_ig.config import config
8 |
9 | from datetime import timedelta
10 | import requests_cache
11 | import time
12 | import os
13 | import json
14 |
15 |
16 | counter = -1
17 | ig_service = None
18 | list_of_instruments = []
19 |
20 |
21 | def login():
22 | expire_after = timedelta(hours=1)
23 | session = requests_cache.CachedSession(
24 | cache_name='cache', backend='sqlite', expire_after=expire_after
25 | )
26 | api_key = increment_api_key()
27 |
28 | global ig_service
29 |
30 | # no cache
31 | ig_service = IGService(
32 | config.username, config.password, api_key, config.acc_type
33 | )
34 | ig_service.create_session()
35 |
36 |
37 | def main():
38 |
39 | login()
40 | map_dataframe = ig_service.fetch_top_level_navigation_nodes()
41 | # list_of_stringNodes = (map_dataframe["nodes"])["id"].tolist()
42 | template_recurse(map_dataframe, ig_service)
43 |
44 |
45 |
46 | def template_recurse(map_dataframe, ig_service):
47 | node_list = map_dataframe["nodes"]["id"].tolist()
48 | # node_list = ["97601","195235"]
49 | name_list = map_dataframe["nodes"]["name"].tolist()
50 | # name_list = ["Indices","Forex"]
51 | set_nodes = set()
52 |
53 | recurse_overNodes(name_list, node_list, set_nodes, ig_service, [])
54 |
55 | def recurse_overNodes(name_list, node_list, set_nodes, ig_service, current_name):
56 | while len(node_list) != 0 :
57 | # needs to be -1 as the last item gets popped
58 | node = node_list[-1]
59 |
60 | if node in set_nodes:
61 | node_list.pop()
62 | name_list.pop()
63 | continue
64 |
65 | current_name.append(name_list[-1])
66 |
67 | set_nodes.add(node)
68 | map_dataframe = get_node_to_node_data(ig_service, node)
69 |
70 | if (map_dataframe["nodes"].size == 0):
71 |
72 | # save the data
73 | try:
74 | epic_id = map_dataframe["markets"]["epic"][0]
75 | if epic_id == "":
76 | raise Exception("No id")
77 | # save data
78 | map_data = get_details_about_epic(ig_service, epic_id)
79 | map_data["instrument"]["location"] = "_".join(current_name)
80 | # data_string = json.dumps(map_data)
81 |
82 | temp = map_data["instrument"].copy()
83 | temp.update(map_data["dealingRules"])
84 | temp.update(map_data["snapshot"])
85 |
86 | global list_of_instruments
87 | list_of_instruments.append(temp)
88 | save_to_file(list_of_instruments)
89 |
90 | except Exception as e:
91 | print(e)
92 |
93 | current_name.pop()
94 |
95 | else:
96 | temp_names = map_dataframe["nodes"]["name"].tolist()
97 | temp_id = map_dataframe["nodes"]["id"].tolist()
98 | recurse_overNodes(temp_names, temp_id, set_nodes, ig_service , current_name)
99 | current_name.pop()
100 |
101 |
102 |
103 |
104 | def get_node_to_node_data(ig_service,node):
105 | while(True):
106 | try:
107 |
108 | map_dataframe = ig_service.fetch_sub_nodes_by_node(node=node)
109 | return map_dataframe
110 | except Exception as e:
111 | print(e)
112 | login()
113 |
114 | def get_details_about_epic(ig_service, epic):
115 | while(True):
116 | try:
117 | map_of_data = ig_service.fetch_market_by_epic(epic)
118 | return map_of_data
119 | except Exception as e:
120 | print(e)
121 | login()
122 | # time.sleep(2)
123 |
124 | def save_to_file(data):
125 |
126 | try:
127 | directory = r"D:/Stock_Analysis/ig-markets-api-python-library-master/Data/SpreadBetting/"
128 |
129 | if not os.path.exists(directory):
130 | os.mkdir(directory)
131 |
132 | file = "instruments_new.csv"
133 | filename= directory+file
134 | df = pd.DataFrame(data)
135 | df.to_csv(filename)
136 |
137 | except Exception as e:
138 | print("failed to write to file " + str(e))
139 |
140 |
141 | def increment_api_key():
142 | key = ""
143 | global counter
144 | flag = True
145 | while (flag):
146 | try:
147 | counter += 1
148 | fp = open("D:\Stock_Analysis\ig-markets-api-python-library-master\generate_api_keys\IG_api_keys_raw.txt")
149 | for i, line in enumerate(fp):
150 | if i == counter:
151 | key = line.split("\n")[0]
152 | flag = False
153 | break
154 |
155 | fp.close()
156 | except:
157 | counter = -1
158 |
159 | return key
160 |
161 |
162 |
163 | if __name__ == '__main__':
164 | main()
165 |
--------------------------------------------------------------------------------
/predefined_functions/algo_doing_simple_tasks.py:
--------------------------------------------------------------------------------
1 | from trading_ig.config import config
2 | import logging
3 |
4 | logger = logging.getLogger(__name__)
5 | logger.setLevel(logging.DEBUG)
6 |
7 | # if you need to cache to DB your requests
8 | from datetime import timedelta
9 | import requests_cache
10 | from getting_realtime_data.data_retrieval import Data_Retrieval
11 | from sending_orders.order_management import Order_Management
12 | from management_of_position.position_management import Position_Management
13 | from predefined_functions.initialisation import Initialisation
14 | from get_data.get_market_data import Get_Market_Data
15 | import time
16 | from datetime import datetime, timedelta
17 | from predefined_functions.defined_functionality import Defined_Functionality
18 | import pandas
19 | import traceback
20 |
21 | # the newest one where you make market order base on price movements 5 or more and try to catch the trend
22 |
23 | class Algo0:
24 | def __init__(self):
25 | logging.basicConfig(level=logging.INFO)
26 | self.df = Defined_Functionality()
27 |
28 | self.list_of_epics = ['IX.D.DOW.DAILY.IP']
29 | # list_of_epics = ['CS.D.EURUSD.TODAY.IP']
30 |
31 | self.df.set_epics_to_look_for(epic_list=self.list_of_epics)
32 |
33 | self.map_epic_data_minute={}
34 | for epic in self.list_of_epics:
35 | self.map_epic_data_minute[epic] = []
36 |
37 |
38 | self.first_timestamp = None
39 | self.high = None
40 | self.low = None
41 |
42 | def setup(self):
43 | self.df.get_market_data()
44 | # self.df.update_stop_level_bands()
45 |
46 |
47 | def run(self):
48 |
49 |
50 | self.df.start_data_from_market_data_socket(self.list_of_epics)
51 |
52 | while(True):
53 | try:
54 | # self.setup()
55 | epic=self.list_of_epics[0]
56 | data = self.df.get_quote_data_from_socket(epic)
57 | print(data)
58 |
59 |
60 | # for epic in self.map_epic_data_minute.keys():
61 | # signals_and_levels = self.signal_generation(epic=epic)
62 | # self.create_orders(epic=epic, signals_levels=signals_and_levels)
63 |
64 | except Exception as e:
65 | print(e, " error in the looping for the defined_functionality")
66 | traceback.print_exc()
67 |
68 |
69 | def create_orders(self, epic, signals_levels):
70 | if signals_levels == None:
71 | return
72 | key = None
73 | if signals_levels["BUY"] != None:
74 | key = "BUY"
75 | elif signals_levels["SELL"] != None:
76 | key = "SELL"
77 |
78 |
79 | position = self.df.find_open_position_by_epic(epic=epic)
80 |
81 | if isinstance(position,pandas.core.series.Series):
82 | print("position already exists", position)
83 | return position
84 |
85 | create_position = self.df.create_open_position(epic=epic, direction=key, size=0.5)
86 |
87 | return create_position
88 |
89 |
90 | def signal_generation(self, epic):
91 | signals_levels = None
92 | # minute_10 = 60 * 10
93 | # minute_10 = 60
94 | minute_10 = 6
95 | datetime_now = datetime.now()
96 | data = None
97 | if (self.first_timestamp != None):
98 | difference = (datetime_now - self.first_timestamp)
99 | data = self.df.get_market_data(epic=epic)
100 | # self.finding_lows_highs(data=data)
101 |
102 | if (difference.seconds > minute_10):
103 | data = self.df.get_market_data(epic=epic)
104 | self.first_timestamp = datetime_now
105 | self.map_epic_data_minute[epic].append(data)
106 | # self.finding_lows_highs(data=data, reset=True)
107 |
108 | else:
109 | data = self.df.get_market_data(epic=epic)
110 | self.first_timestamp = datetime_now
111 |
112 | self.map_epic_data_minute[epic].append(data)
113 | # self.finding_lows_highs(data=data)
114 |
115 | if len(self.map_epic_data_minute[epic]) > 3:
116 | self.map_epic_data_minute[epic].pop(0)
117 |
118 |
119 | sell_level = None
120 | buy_level = None
121 |
122 | object_epic_data = self.map_epic_data_minute[epic][-1]
123 | bid = object_epic_data["snapshot"]["bid"]
124 | offer = object_epic_data["snapshot"]["offer"]
125 | high = object_epic_data["snapshot"]["high"]
126 | low = object_epic_data["snapshot"]["low"]
127 |
128 | object_epic_data = self.map_epic_data_minute[epic][-2]
129 | bid_old = object_epic_data["snapshot"]["bid"]
130 | offer_old = object_epic_data["snapshot"]["offer"]
131 | high_old = object_epic_data["snapshot"]["high"]
132 | low_old = object_epic_data["snapshot"]["low"]
133 |
134 | offer_diff = offer - offer_old
135 | bid_diff = bid - bid_old
136 |
137 | if offer_diff > 10:
138 | buy_level = 1
139 | elif bid_diff < -10:
140 | sell_level = 1
141 |
142 | self.map_epic_data_minute[epic] = []
143 | # instead here we are using bid/offer
144 |
145 | if (sell_level == None) and (buy_level == None):
146 | return None
147 |
148 | signals_levels = {
149 | "SELL": sell_level,
150 | "BUY": buy_level
151 | }
152 |
153 | return signals_levels
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/predefined_functions/algo_minute_on_quotes.py:
--------------------------------------------------------------------------------
1 | from trading_ig.config import config
2 | import logging
3 |
4 | logger = logging.getLogger(__name__)
5 | logger.setLevel(logging.DEBUG)
6 |
7 | # if you need to cache to DB your requests
8 | from datetime import timedelta
9 | import requests_cache
10 | from getting_realtime_data.data_retrieval import Data_Retrieval
11 | from sending_orders.order_management import Order_Management
12 | from management_of_position.position_management import Position_Management
13 | from predefined_functions.initialisation import Initialisation
14 | from get_data.get_market_data import Get_Market_Data
15 | import time
16 | from datetime import datetime, timedelta
17 | from predefined_functions.defined_functionality import Defined_Functionality
18 | import pandas
19 | import traceback
20 |
21 | # the newest one where you make market order base on price movements 5 or more and try to catch the trend
22 |
23 | class Algo0:
24 | def __init__(self):
25 | logging.basicConfig(level=logging.INFO)
26 | self.df = Defined_Functionality()
27 |
28 | list_of_epics = ['IX.D.DOW.DAILY.IP']
29 | # list_of_epics = ['CS.D.EURUSD.TODAY.IP']
30 |
31 | self.df.set_epics_to_look_for(epic_list=list_of_epics)
32 |
33 | self.map_epic_data_minute={}
34 | for epic in list_of_epics:
35 | self.map_epic_data_minute[epic] = []
36 |
37 |
38 | self.first_timestamp = None
39 | self.high = None
40 | self.low = None
41 |
42 | def setup(self):
43 | self.df.initialise_connection()
44 | time.sleep(2)
45 | self.df.get_market_data()
46 | self.df.update_stop_level_bands()
47 |
48 |
49 | def run(self):
50 |
51 | while(True):
52 | try:
53 | self.setup()
54 |
55 | for epic in self.map_epic_data_minute.keys():
56 | signals_and_levels = self.signal_generation(epic=epic)
57 | self.create_orders(epic=epic, signals_levels=signals_and_levels)
58 |
59 | except Exception as e:
60 | print(e, " error in the looping for the defined_functionality")
61 | traceback.print_exc()
62 |
63 |
64 | def create_orders(self, epic, signals_levels):
65 | if signals_levels == None:
66 | return
67 | key = None
68 | if signals_levels["BUY"] != None:
69 | key = "BUY"
70 | elif signals_levels["SELL"] != None:
71 | key = "SELL"
72 |
73 |
74 | position = self.df.find_open_position_by_epic(epic=epic)
75 |
76 | if isinstance(position,pandas.core.series.Series):
77 | print("position already exists", position)
78 | return position
79 |
80 | create_position = self.df.create_open_position(epic=epic, direction=key, size=0.5)
81 |
82 | return create_position
83 |
84 |
85 | def signal_generation(self, epic):
86 | signals_levels = None
87 | # minute_10 = 60 * 10
88 | # minute_10 = 60
89 | minute_10 = 6
90 | datetime_now = datetime.now()
91 | data = None
92 | if (self.first_timestamp != None):
93 | difference = (datetime_now - self.first_timestamp)
94 | data = self.df.get_market_data(epic=epic)
95 | # self.finding_lows_highs(data=data)
96 |
97 | if (difference.seconds > minute_10):
98 | data = self.df.get_market_data(epic=epic)
99 | self.first_timestamp = datetime_now
100 | self.map_epic_data_minute[epic].append(data)
101 | # self.finding_lows_highs(data=data, reset=True)
102 |
103 | else:
104 | data = self.df.get_market_data(epic=epic)
105 | self.first_timestamp = datetime_now
106 |
107 | self.map_epic_data_minute[epic].append(data)
108 | # self.finding_lows_highs(data=data)
109 |
110 | if len(self.map_epic_data_minute[epic]) > 3:
111 | self.map_epic_data_minute[epic].pop(0)
112 |
113 |
114 | sell_level = None
115 | buy_level = None
116 |
117 | object_epic_data = self.map_epic_data_minute[epic][-1]
118 | bid = object_epic_data["snapshot"]["bid"]
119 | offer = object_epic_data["snapshot"]["offer"]
120 | high = object_epic_data["snapshot"]["high"]
121 | low = object_epic_data["snapshot"]["low"]
122 |
123 | object_epic_data = self.map_epic_data_minute[epic][-2]
124 | bid_old = object_epic_data["snapshot"]["bid"]
125 | offer_old = object_epic_data["snapshot"]["offer"]
126 | high_old = object_epic_data["snapshot"]["high"]
127 | low_old = object_epic_data["snapshot"]["low"]
128 |
129 | offer_diff = offer - offer_old
130 | bid_diff = bid - bid_old
131 | # as we are following the trends
132 | # # if offer_diff > 5:
133 | # if offer_diff > 0:
134 | # buy_level = 1
135 | # # elif offer_diff < -5:
136 | # elif offer_diff < 0:
137 | # sell_level = 1
138 |
139 | if offer_diff > 10:
140 | buy_level = 1
141 | elif bid_diff < -10:
142 | sell_level = 1
143 |
144 | self.map_epic_data_minute[epic] = []
145 | # instead here we are using bid/offer
146 |
147 | if (sell_level == None) and (buy_level == None):
148 | return None
149 |
150 | signals_levels = {
151 | "SELL": sell_level,
152 | "BUY": buy_level
153 | }
154 |
155 | return signals_levels
156 |
157 | def finding_lows_highs(self, data, reset = False):
158 |
159 | bid = data["snapshot"]["bid"]
160 | offer = data["snapshot"]["offer"]
161 |
162 | if reset:
163 | epic = data["instrument"]["epic"]
164 | object_dict = self.map_epic_data_minute[epic][-1]
165 | object_dict["snapshot"]["high"] = self.high
166 | object_dict["snapshot"]["low"] = self.low
167 | self.map_epic_data_minute[epic][-1] = object_dict
168 | # start looking at the new interval
169 | if self.high == None or reset:
170 | self.high = offer
171 | if self.low == None or reset:
172 | self.low = bid
173 |
174 | if bid < self.low:
175 | self.low = bid
176 | if offer > self.high:
177 | self.high = offer
178 |
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/predefined_functions/algo_close_positons_in_profit.py:
--------------------------------------------------------------------------------
1 | from trading_ig.config import config
2 | import logging
3 |
4 | logger = logging.getLogger(__name__)
5 | logger.setLevel(logging.DEBUG)
6 |
7 | # if you need to cache to DB your requests
8 | from datetime import timedelta
9 | import requests_cache
10 | from getting_realtime_data.data_retrieval import Data_Retrieval
11 | from sending_orders.order_management import Order_Management
12 | from management_of_position.position_management import Position_Management
13 | from predefined_functions.initialisation import Initialisation
14 | from get_data.get_market_data import Get_Market_Data
15 | import time
16 | from datetime import datetime, timedelta
17 | from predefined_functions.defined_functionality import Defined_Functionality
18 | import pandas
19 | import traceback
20 |
21 |
22 | class Algo0:
23 | def __init__(self):
24 | self.df = Defined_Functionality()
25 |
26 |
27 | def setup(self):
28 | # self.df.get_market_data()
29 | self.df.update_stop_level_bands()
30 |
31 |
32 | def run(self):
33 |
34 | while(True):
35 | try:
36 | self.setup()
37 |
38 | except Exception as e:
39 | print(e, " error in the looping for the defined_functionality")
40 | traceback.print_exc()
41 |
42 |
43 |
44 | def create_orders(self, epic, signals_levels):
45 | if signals_levels == None:
46 | return
47 | key = None
48 | if signals_levels["BUY"] != None:
49 | key = "BUY"
50 | elif signals_levels["SELL"] != None:
51 | key = "SELL"
52 |
53 | self.df.cancel_orders_by_epic(epic=epic)
54 | position = self.df.find_open_position_by_epic(epic=epic)
55 | if isinstance(position,pandas.core.series.Series):
56 | print("position already exists", position)
57 | return position
58 |
59 | order = self.df.create_working_order_at_point(epic=epic, direction=key,price_order_level=signals_levels[key])
60 | return order
61 |
62 |
63 | # def signal_generation(self, epic):
64 | # signals_levels = None
65 | # # minute_10 = 60 * 10
66 | # minute_10 = 60 * 10
67 | # datetime_now = datetime.now()
68 | # data = None
69 | # if (self.first_timestamp != None):
70 | # difference = (datetime_now - self.first_timestamp)
71 | # data = self.df.get_market_data(epic=epic)
72 | # self.finding_lows_highs(data=data)
73 | #
74 | # if (difference.seconds > minute_10):
75 | # data = self.df.get_market_data(epic=epic)
76 | # self.first_timestamp = datetime_now
77 | # self.map_epic_data_10_minute[epic].append(data)
78 | # self.finding_lows_highs(data=data, reset=True)
79 | #
80 | # else:
81 | # data = self.df.get_market_data(epic=epic)
82 | # self.first_timestamp = datetime_now
83 | #
84 | # self.map_epic_data_10_minute[epic].append(data)
85 | # self.finding_lows_highs(data=data)
86 | #
87 | # if len(self.map_epic_data_10_minute[epic]) > 4:
88 | # self.map_epic_data_10_minute[epic].pop(0)
89 | #
90 | #
91 | # sell_level = None
92 | # buy_level = None
93 | #
94 | # difference_bid = []
95 | # difference_offer = []
96 | # difference_low = []
97 | # difference_high = []
98 | #
99 | # object_epic_data = self.map_epic_data_10_minute[epic][0]
100 | # bid = object_epic_data["snapshot"]["bid"]
101 | # offer = object_epic_data["snapshot"]["offer"]
102 | # high = object_epic_data["snapshot"]["high"]
103 | # low = object_epic_data["snapshot"]["low"]
104 | #
105 | # for i in range(1, len(self.map_epic_data_10_minute[epic])):
106 | #
107 | # object_epic_data = self.map_epic_data_10_minute[epic][i]
108 | # bid = object_epic_data["snapshot"]["bid"] - bid
109 | # offer = object_epic_data["snapshot"]["offer"] - offer
110 | # high = object_epic_data["snapshot"]["high"] - high
111 | # low = object_epic_data["snapshot"]["low"] - low
112 | #
113 | # difference_bid.append(bid)
114 | # difference_offer.append(offer)
115 | # difference_low.append(low)
116 | # difference_high.append(high)
117 | # # the high/low becomes the levels we enter orders at
118 | # bid = object_epic_data["snapshot"]["bid"]
119 | # offer = object_epic_data["snapshot"]["offer"]
120 | # high = object_epic_data["snapshot"]["high"]
121 | # low = object_epic_data["snapshot"]["low"]
122 | #
123 | # self.map_epic_data_10_minute[epic] = []
124 | #
125 | # offer_average = sum(difference_offer)/len(difference_offer)
126 | # bid_average = sum(difference_bid)/len(difference_bid)
127 | #
128 | # # we have gone long we should now short
129 | # if (bid_average > 0 and offer_average> 0):
130 | # sell_level = high
131 | # elif (bid_average < 0 and offer_average < 0):
132 | # buy_level = low
133 | #
134 | # # instead here we are using bid/offer
135 | #
136 | # if (sell_level == None) and (buy_level == None):
137 | # return None
138 | #
139 | # signals_levels = {
140 | # "SELL": sell_level,
141 | # "BUY": buy_level
142 | # }
143 | #
144 | # return signals_levels
145 | #
146 | # def finding_lows_highs(self, data, reset = False):
147 | #
148 | # bid = data["snapshot"]["bid"]
149 | # offer = data["snapshot"]["offer"]
150 | #
151 | # if reset:
152 | # epic = data["instrument"]["epic"]
153 | # object_dict = self.map_epic_data_10_minute[epic][-1]
154 | # object_dict["snapshot"]["high"] = self.high
155 | # object_dict["snapshot"]["low"] = self.low
156 | # self.map_epic_data_10_minute[epic][-1] = object_dict
157 | # # start looking at the new interval
158 | # if self.high == None or reset:
159 | # self.high = offer
160 | # if self.low == None or reset:
161 | # self.low = bid
162 | #
163 | # if bid < self.low:
164 | # self.low = bid
165 | # if offer > self.high:
166 | # self.high = offer
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/Linked_to_biggest_previous_day_difference_in_price/adding_realtime_IG_data_to_file.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | """
5 | IG Markets REST API sample with Python
6 | 2015 FemtoTrader
7 | """
8 |
9 | from trading_ig import IGService
10 | from trading_ig.config import config
11 | import logging
12 | # format to
13 | # # from folder.file import class
14 | # from getting_instrument_based_data.navigate_tree import NavigateTree
15 |
16 | logger = logging.getLogger(__name__)
17 | logger.setLevel(logging.DEBUG)
18 |
19 | # if you need to cache to DB your requests
20 | from datetime import timedelta
21 | import requests_cache
22 | import time
23 | import os
24 | import json
25 | import pandas as pd
26 |
27 |
28 | counter = -1
29 | ig_service = None
30 |
31 |
32 |
33 | def login():
34 | expire_after = timedelta(hours=1)
35 | session = requests_cache.CachedSession(
36 | cache_name='cache', backend='sqlite', expire_after=expire_after
37 | )
38 | api_key = increment_api_key()
39 |
40 | global ig_service
41 |
42 | # no cache
43 | ig_service = IGService(
44 | config.username, config.password, api_key, config.acc_type
45 | )
46 | ig_service.create_session()
47 |
48 |
49 |
50 | def main():
51 |
52 | login()
53 |
54 | date = "2020-12-10_2021-02-10"
55 | # date = "2020-09-10_2020-12-10"
56 | time_interval = "5Min"
57 | paths = [
58 |
59 | # "diff_from_morning_minus_afternoon_2020-12-01_2020-12-02_1Min",
60 | # "diff_from_morning_minus_afternoon_2020-12-02_2020-12-03_1Min",
61 | # "diff_from_morning_minus_afternoon_2020-12-03_2020-12-04_1Min",
62 | # "diff_from_morning_minus_afternoon_2020-12-04_2020-12-05_1Min",
63 | # "diff_from_morning_minus_afternoon_2020-12-05_2020-12-06_1Min",
64 | # "diff_from_morning_minus_afternoon_2020-12-06_2020-12-07_1Min",
65 | # "diff_from_morning_minus_afternoon_2020-12-07_2020-12-08_1Min",
66 | # "diff_from_morning_minus_afternoon_2020-12-08_2020-12-09_1Min",
67 | # "diff_from_morning_minus_afternoon_2020-12-09_2020-12-10_1Min",
68 | # "diff_from_morning_minus_afternoon_2020-12-10_2020-12-11_1Min",
69 | # "diff_from_morning_minus_afternoon_2020-12-11_2020-12-12_1Min",
70 | # "diff_from_morning_minus_afternoon_2020-12-14_2020-12-15_1Min",
71 | # "diff_from_morning_minus_afternoon_2020-12-15_2020-12-16_1Min",
72 | # "diff_from_morning_minus_afternoon_2020-12-16_2020-12-17_1Min",
73 | # "diff_from_morning_minus_afternoon_2020-12-17_2020-12-18_1Min",
74 | # "diff_from_morning_minus_afternoon_2020-12-18_2020-12-19_1Min",
75 | # "diff_from_morning_minus_afternoon_2020-12-21_2020-12-22_1Min",
76 | # "diff_from_morning_minus_afternoon_" + date + "_" + time_interval
77 | "diff_from_start_minus_end_" + date + "_" + time_interval
78 | ]
79 |
80 | for path in paths:
81 | get_data(path, date, time_interval)
82 |
83 |
84 |
85 | def get_data(file_name, date, time_interval):
86 |
87 | path = r"D:\Stock_Analysis\IG_Data_Fixing\Results\morning_afternoon_diffs\\"+file_name+".csv"
88 | dataframe = pd.read_csv(path)
89 | dataframe.rename(columns={"Unnamed: 0": "Datetime"}, inplace=True)
90 | Instrument_Data = dataframe.set_index("Datetime").T
91 |
92 | histroical_path_location = "D:\Data\IG_Instrument\historical_data\\" + time_interval + "\\" + date
93 |
94 | holding_list = []
95 |
96 | for index in range(Instrument_Data.index.size):
97 | # save the data
98 | try:
99 |
100 |
101 | name = Instrument_Data.iloc[index].name
102 | epic = name.split("_ID_")[1]
103 | data = get_details_about_epic(epic)
104 | # get the magin requirement from here ---------------------------------------------------------------------------------------------
105 | data = json.loads(json.dumps(data))
106 | #
107 | # map_of_items = {
108 | # "value" : data["instrument"]["marginFactor"],
109 | # "unit" : data["instrument"]["marginFactorUnit"]}
110 | #
111 | # difference_required = map_of_items["value"]
112 | # # otherwise the unit is POINTS
113 | # if map_of_items["unit"] == "PERCENTAGE":
114 | # difference_required = difference_required / 100
115 | #
116 | # difference_required * current_price
117 | temp = data["instrument"].copy()
118 | temp.update(data["dealingRules"])
119 | temp.update(data["snapshot"])
120 | temp["file_name"] = name
121 | temp["diff_score_across_time"] = Instrument_Data[Instrument_Data.columns[0]].iloc[index]
122 |
123 |
124 | whole_file_location = os.path.join(histroical_path_location, name)
125 | historical_data = pd.read_csv(whole_file_location, header=[0, 1], index_col=0)
126 | historical_data.index = pd.to_datetime(historical_data.index)
127 |
128 | bid = historical_data.iloc[0]["bid"]["Close"]
129 | ask = historical_data.iloc[0]["ask"]["Close"]
130 | spread = ask - bid
131 |
132 | temp["spread"] = spread
133 | temp["average"] = (bid + ask) / 2.0
134 | temp["diff_high-low"] = historical_data["bid"]["High"].max() - historical_data["bid"]["Low"].min()
135 | # could divide by zero and cause an error but would be caught by try and except clause
136 | temp["percent_spread-hl"] = (temp["spread"] / temp["diff_high-low"] * 100)
137 |
138 |
139 | holding_list.append(temp)
140 |
141 | dataframe = pd.DataFrame(holding_list)
142 |
143 | dataframe.to_csv("D:\Stock_Analysis\IG_Data_Fixing\Results\morn_after_diffs_instrument_data_added\\"+file_name+"_instrument_data_added.csv")
144 |
145 | except Exception as e:
146 | print(e)
147 |
148 |
149 | def get_details_about_epic(epic):
150 | global ig_service
151 | while(True):
152 | try:
153 | map_of_data = ig_service.fetch_market_by_epic(epic)
154 | return map_of_data
155 | except Exception as e:
156 | print(e)
157 | login()
158 |
159 |
160 | def increment_api_key():
161 | key = ""
162 | global counter
163 | flag = True
164 | while (flag):
165 | try:
166 | counter += 1
167 | # has 12000 api keys
168 | fp = open("D:\Stock_Analysis\ig-markets-api-python-library-master\generate_api_keys\IG_api_keys_raw.txt")
169 | for i, line in enumerate(fp):
170 | if i == counter:
171 | key = line.split("\n")[0]
172 | flag = False
173 | break
174 |
175 | fp.close()
176 | except:
177 | counter = -1
178 |
179 | return key
180 |
181 |
182 |
183 | if __name__ == '__main__':
184 | main()
185 |
--------------------------------------------------------------------------------
/predefined_functions/algo_ten_minute.py:
--------------------------------------------------------------------------------
1 | from trading_ig.config import config
2 | import logging
3 |
4 | logger = logging.getLogger(__name__)
5 | logger.setLevel(logging.DEBUG)
6 |
7 | # if you need to cache to DB your requests
8 | from datetime import timedelta
9 | import requests_cache
10 | from getting_realtime_data.data_retrieval import Data_Retrieval
11 | from sending_orders.order_management import Order_Management
12 | from management_of_position.position_management import Position_Management
13 | from predefined_functions.initialisation import Initialisation
14 | from get_data.get_market_data import Get_Market_Data
15 | import time
16 | from datetime import datetime, timedelta
17 | from predefined_functions.defined_functionality import Defined_Functionality
18 | import pandas
19 | import traceback
20 |
21 |
22 | class Algo0:
23 | def __init__(self):
24 | logging.basicConfig(level=logging.INFO)
25 | self.df = Defined_Functionality()
26 |
27 | # list_of_epics = ['IX.D.DOW.DAILY.IP']
28 | list_of_epics = ['CS.D.EURUSD.TODAY.IP']
29 |
30 | self.df.set_epics_to_look_for(epic_list=list_of_epics)
31 |
32 | self.map_epic_data_10_minute={}
33 | for epic in list_of_epics:
34 | self.map_epic_data_10_minute[epic] = []
35 |
36 |
37 | self.first_timestamp = None
38 | self.high = None
39 | self.low = None
40 |
41 | def setup(self):
42 | self.df.initialise_connection()
43 | time.sleep(2)
44 | self.df.get_market_data()
45 | self.df.update_stop_level_bands()
46 |
47 |
48 | def run(self):
49 |
50 | while(True):
51 | try:
52 | self.setup()
53 |
54 | for epic in self.map_epic_data_10_minute.keys():
55 | signals_and_levels = self.signal_generation(epic=epic)
56 | self.create_orders(epic=epic, signals_levels=signals_and_levels)
57 |
58 | except Exception as e:
59 | print(e, " error in the looping for the defined_functionality")
60 | traceback.print_exc()
61 |
62 |
63 | def create_orders(self, epic, signals_levels):
64 | if signals_levels == None:
65 | return
66 | key = None
67 | if signals_levels["BUY"] != None:
68 | key = "BUY"
69 | elif signals_levels["SELL"] != None:
70 | key = "SELL"
71 |
72 | self.df.cancel_orders_by_epic(epic=epic)
73 | position = self.df.find_open_position_by_epic(epic=epic)
74 | if isinstance(position,pandas.core.series.Series):
75 | print("position already exists", position)
76 | return position
77 |
78 | order = self.df.create_working_order_at_point(epic=epic, direction=key,price_order_level=signals_levels[key])
79 | return order
80 |
81 |
82 | def signal_generation(self, epic):
83 | signals_levels = None
84 | # minute_10 = 60 * 10
85 | minute_10 = 60 * 10
86 | datetime_now = datetime.now()
87 | data = None
88 | if (self.first_timestamp != None):
89 | difference = (datetime_now - self.first_timestamp)
90 | data = self.df.get_market_data(epic=epic)
91 | self.finding_lows_highs(data=data)
92 |
93 | if (difference.seconds > minute_10):
94 | data = self.df.get_market_data(epic=epic)
95 | self.first_timestamp = datetime_now
96 | self.map_epic_data_10_minute[epic].append(data)
97 | self.finding_lows_highs(data=data, reset=True)
98 |
99 | else:
100 | data = self.df.get_market_data(epic=epic)
101 | self.first_timestamp = datetime_now
102 |
103 | self.map_epic_data_10_minute[epic].append(data)
104 | self.finding_lows_highs(data=data)
105 |
106 | if len(self.map_epic_data_10_minute[epic]) > 4:
107 | self.map_epic_data_10_minute[epic].pop(0)
108 |
109 |
110 | sell_level = None
111 | buy_level = None
112 |
113 | difference_bid = []
114 | difference_offer = []
115 | difference_low = []
116 | difference_high = []
117 |
118 | object_epic_data = self.map_epic_data_10_minute[epic][0]
119 | bid = object_epic_data["snapshot"]["bid"]
120 | offer = object_epic_data["snapshot"]["offer"]
121 | high = object_epic_data["snapshot"]["high"]
122 | low = object_epic_data["snapshot"]["low"]
123 |
124 | for i in range(1, len(self.map_epic_data_10_minute[epic])):
125 |
126 | object_epic_data = self.map_epic_data_10_minute[epic][i]
127 | bid = object_epic_data["snapshot"]["bid"] - bid
128 | offer = object_epic_data["snapshot"]["offer"] - offer
129 | high = object_epic_data["snapshot"]["high"] - high
130 | low = object_epic_data["snapshot"]["low"] - low
131 |
132 | difference_bid.append(bid)
133 | difference_offer.append(offer)
134 | difference_low.append(low)
135 | difference_high.append(high)
136 | # the high/low becomes the levels we enter orders at
137 | bid = object_epic_data["snapshot"]["bid"]
138 | offer = object_epic_data["snapshot"]["offer"]
139 | high = object_epic_data["snapshot"]["high"]
140 | low = object_epic_data["snapshot"]["low"]
141 |
142 | self.map_epic_data_10_minute[epic] = []
143 |
144 | offer_average = sum(difference_offer)/len(difference_offer)
145 | bid_average = sum(difference_bid)/len(difference_bid)
146 |
147 | # we have gone long we should now short
148 | if (bid_average > 0 and offer_average> 0):
149 | sell_level = high
150 | elif (bid_average < 0 and offer_average < 0):
151 | buy_level = low
152 |
153 | # instead here we are using bid/offer
154 |
155 | if (sell_level == None) and (buy_level == None):
156 | return None
157 |
158 | signals_levels = {
159 | "SELL": sell_level,
160 | "BUY": buy_level
161 | }
162 |
163 | return signals_levels
164 |
165 | def finding_lows_highs(self, data, reset = False):
166 |
167 | bid = data["snapshot"]["bid"]
168 | offer = data["snapshot"]["offer"]
169 |
170 | if reset:
171 | epic = data["instrument"]["epic"]
172 | object_dict = self.map_epic_data_10_minute[epic][-1]
173 | object_dict["snapshot"]["high"] = self.high
174 | object_dict["snapshot"]["low"] = self.low
175 | self.map_epic_data_10_minute[epic][-1] = object_dict
176 | # start looking at the new interval
177 | if self.high == None or reset:
178 | self.high = offer
179 | if self.low == None or reset:
180 | self.low = bid
181 |
182 | if bid < self.low:
183 | self.low = bid
184 | if offer > self.high:
185 | self.high = offer
186 |
187 |
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/tests/test_ig_service.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | integration tests
6 | """
7 |
8 | import pandas as pd
9 | import requests
10 | # import requests_cache
11 | from datetime import datetime, timedelta
12 | import six
13 | import time
14 |
15 | # import pprint
16 |
17 | import trading_ig
18 | from trading_ig import IGService
19 | from trading_ig.utils import remove
20 | from trading_ig.config import config
21 |
22 | """
23 | Environment variables must be set using
24 |
25 | export IG_SERVICE_USERNAME=""
26 | export IG_SERVICE_PASSWORD=""
27 | export IG_SERVICE_API_KEY=""
28 | export IG_SERVICE_ACC_TYPE="DEMO" # LIVE / DEMO
29 | export IG_SERVICE_ACC_NUMBER=""
30 |
31 | """
32 |
33 | CACHE_NAME = "cache"
34 |
35 | remove(CACHE_NAME)
36 |
37 |
38 | def test_ig_service():
39 |
40 | delay_for_ig = 5
41 |
42 | def wait(delay):
43 | print(
44 | "Wait %s s to avoid 'error.public-api.exceeded-account-allowance'" % delay
45 | )
46 | time.sleep(delay)
47 |
48 | # session_cached = requests_cache.CachedSession(
49 | # cache_name=CACHE_NAME, backend="sqlite", expire_after=timedelta(hours=1)
50 | # )
51 | session_not_cached = requests.Session()
52 |
53 | # for i, session in enumerate([session_cached, session_cached, session_not_cached]):
54 | for i, session in enumerate([session_not_cached]):
55 |
56 | # pp = pprint.PrettyPrinter(indent=4)
57 |
58 | assert isinstance(trading_ig.__version__, six.string_types)
59 |
60 | ig_service = IGService(
61 | config.username, config.password, config.api_key, config.acc_type, session
62 | )
63 |
64 | ig_service.create_session()
65 |
66 | print("%d - fetch_accounts" % i)
67 | response = ig_service.fetch_accounts()
68 | preferred = response.loc[response["preferred"] == True]
69 | assert all(preferred["balance"] > 0)
70 |
71 | print("")
72 |
73 | print("fetch_account_activity_by_period")
74 | response = ig_service.fetch_account_activity_by_period(10000)
75 | print(response)
76 | assert isinstance(response, pd.DataFrame)
77 |
78 | print("")
79 |
80 | print("fetch_transaction_history_by_type_and_period")
81 | response = ig_service.fetch_transaction_history_by_type_and_period(10000, "ALL")
82 | print(response)
83 | assert isinstance(response, pd.DataFrame)
84 |
85 | wait(delay_for_ig)
86 | print("")
87 |
88 | print("fetch_open_positions")
89 | response = ig_service.fetch_open_positions()
90 | print(response)
91 | assert isinstance(response, pd.DataFrame)
92 |
93 | print("")
94 |
95 | print("fetch_working_orders")
96 | response = ig_service.fetch_working_orders()
97 | print(response)
98 | assert isinstance(response, pd.DataFrame)
99 |
100 | print("")
101 |
102 | print("fetch_top_level_navigation_nodes")
103 | response = ig_service.fetch_top_level_navigation_nodes()
104 | print(response) # dict with nodes and markets
105 | assert isinstance(response, dict)
106 | market_id = response["nodes"]["id"].iloc[0]
107 |
108 | print("")
109 |
110 | print("fetch_client_sentiment_by_instrument")
111 | response = ig_service.fetch_client_sentiment_by_instrument(market_id)
112 | print(response)
113 | assert isinstance(response, dict)
114 |
115 | print("")
116 |
117 | # print("fetch_related_client_sentiment_by_instrument")
118 | # response = ig_service.fetch_related_client_sentiment_by_instrument(market_id)
119 | # print(response)
120 | # assert isinstance(response, pd.DataFrame)
121 |
122 | print("")
123 |
124 | print("fetch_sub_nodes_by_node")
125 | node = market_id
126 | response = ig_service.fetch_sub_nodes_by_node(node)
127 | print(response)
128 | assert isinstance(response["markets"], pd.DataFrame)
129 | assert isinstance(response["nodes"], pd.DataFrame)
130 |
131 | print("")
132 | wait(delay_for_ig)
133 |
134 | print("fetch_all_watchlists")
135 | response = ig_service.fetch_all_watchlists()
136 | print(response)
137 | assert isinstance(response, pd.DataFrame)
138 | watchlist_id = response["id"].iloc[0] # u'Popular Markets'
139 |
140 | print("")
141 |
142 | print("fetch_watchlist_markets")
143 | response = ig_service.fetch_watchlist_markets(watchlist_id)
144 | print(response)
145 | assert isinstance(response, pd.DataFrame)
146 | # epic = 'CS.D.EURUSD.MINI.IP'
147 | # epic = u'IX.D.CAC.IDF.IP'
148 | epic = response["epic"].iloc[0]
149 |
150 | print("")
151 |
152 | print("fetch_market_by_epic")
153 | response = ig_service.fetch_market_by_epic(epic)
154 | print(response)
155 | # pp.pprint(response)
156 | assert isinstance(response, dict)
157 |
158 | print("")
159 |
160 | print("search_markets")
161 | search_term = "EURUSD"
162 | # search_term = 'SPY'
163 | response = ig_service.search_markets(search_term)
164 | print(response)
165 | assert isinstance(response, pd.DataFrame)
166 |
167 | print("")
168 | wait(delay_for_ig)
169 |
170 | print("fetch_historical_prices_by_epic_and_num_points")
171 |
172 | # epic = 'CS.D.EURUSD.MINI.IP'
173 | # epic = 'IX.D.ASX.IFM.IP' # US 500 (SPY)
174 | # epic = 'IX.D.ASX.IFM.IP' # US (SPY) - mini
175 | # MINUTE, MINUTE_2, MINUTE_3, MINUTE_5, MINUTE_10, MINUTE_15,
176 | # MINUTE_30, HOUR, HOUR_2, HOUR_3, HOUR_4, DAY, WEEK, MONTH
177 | # resolution = 'HOUR'
178 | # http://pandas.pydata.org/pandas-docs/stable/timeseries.html#dateoffset-objects
179 | resolution = "H"
180 | num_points = 10
181 | response = ig_service.fetch_historical_prices_by_epic_and_num_points(
182 | epic, resolution, num_points
183 | )
184 | print(response)
185 | # print(response['prices']['price'])
186 | # print(response['prices']['price']['ask'])
187 | # print(response['prices']['volume'])
188 | assert isinstance(response["allowance"], dict)
189 | # assert(isinstance(response['prices']['volume'], pd.Series))
190 | # assert(isinstance(response['prices']['price'], pd.Panel))
191 | assert isinstance(response["prices"], pd.DataFrame)
192 |
193 | print("")
194 | wait(delay_for_ig)
195 |
196 | print("fetch_historical_prices_by_epic_and_date_range")
197 | end_date = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
198 | start_date = end_date - timedelta(days=3)
199 | response = ig_service.fetch_historical_prices_by_epic_and_date_range(
200 | epic, resolution, start_date, end_date
201 | )
202 | print(response)
203 | assert isinstance(response["allowance"], dict)
204 | # assert(isinstance(response['prices']['volume'], pd.Series))
205 | # assert(isinstance(response['prices']['price'], pd.Panel))
206 | assert isinstance(response["prices"], pd.DataFrame)
207 |
208 | print("")
209 | wait(delay_for_ig)
210 |
211 | remove(CACHE_NAME)
212 |
--------------------------------------------------------------------------------
/sending_orders/order_management.py:
--------------------------------------------------------------------------------
1 | from trading_ig import IGService
2 | from trading_ig.config import config
3 | import logging
4 |
5 | logger = logging.getLogger(__name__)
6 | logger.setLevel(logging.INFO)
7 |
8 | # if you need to cache to DB your requests
9 | from datetime import timedelta
10 | import requests_cache
11 |
12 | from predefined_functions.initialisation import Initialisation
13 |
14 | class Order_Management():
15 | def __init__(self):
16 | logging.basicConfig(level=logging.INFO)
17 | self.log = logging.getLogger(__name__)
18 | # set object and then set connection
19 | self.initial = Initialisation()
20 | self.initialise_connection()
21 |
22 | def initialise_connection(self):
23 | self.ig_service = self.initial.initialise_connection()
24 | self.ig_service.create_session()
25 |
26 | # limit orders
27 | def create_working_order(self, direction, epic, size, price, stop_distance,limit_distance,force_open=False):
28 | currency_code = "GBP"
29 | direction = direction
30 | epic = epic
31 | expiry = "DFB"
32 | if force_open == True:
33 | guaranteed_stop = False
34 | else:
35 | guaranteed_stop = True
36 | # entering price
37 | level = price
38 | # Pound per point size
39 | size = size
40 | time_in_force = "GOOD_TILL_CANCELLED"
41 | # LIMIT orders are now STOP
42 | order_type = "STOP"
43 | limit_distance = limit_distance
44 | stop_distance = stop_distance
45 |
46 | # currency_code = "GBP"
47 | # direction = "SELL"
48 | # epic = "CS.D.BITCOIN.TODAY.IP"
49 | # expiry = "DFB"
50 | # guaranteed_stop = False
51 | # # entering price
52 | # level = 13109
53 | # # Pound per point size
54 | # size = 0.50
55 | # time_in_force = "GOOD_TILL_CANCELLED"
56 | # order_type = "LIMIT"
57 | # limit_distance = 4000.0
58 | # stop_distance = 160.0
59 |
60 | # """Creates an OTC working order"""
61 |
62 | try:
63 | response = self.ig_service.create_working_order(
64 | currency_code=currency_code,
65 | direction=direction,
66 | epic=epic,
67 | expiry=expiry,
68 | guaranteed_stop=guaranteed_stop,
69 | level=level,
70 | size=size,
71 | time_in_force=time_in_force,
72 | order_type=order_type,
73 | limit_distance=limit_distance,
74 | stop_distance=stop_distance,
75 | force_open=force_open
76 | )
77 |
78 | return response
79 | except Exception as e:
80 | self.log.info(str(e) + " error occurred when creating a working order")
81 | return None
82 |
83 | # market orders
84 | def create_open_position(self, direction, epic, size, limit_distance, stop_distance, force_open):
85 | currency_code = "GBP"
86 | direction = direction
87 | epic = epic
88 | expiry = "DFB"
89 | # no matter what you are doing force open always has to be True other wise stop losses do not work
90 | force_open = force_open
91 | if force_open:
92 | guaranteed_stop = False
93 | else:
94 | guaranteed_stop = True
95 |
96 | stop_distance = stop_distance
97 | size = size
98 | trailing_stop = False
99 | trailing_stop_increment = None
100 | trailing_stop_distance = None
101 | time_in_force = "FILL_OR_KILL"
102 | order_type = "MARKET"
103 | limit_distance = limit_distance
104 |
105 | try:
106 | response = self.ig_service.create_open_position(
107 | currency_code=currency_code,
108 | direction=direction,
109 | epic=epic,
110 | expiry=expiry,
111 | # no matter what you are doing force open always has to be True other wise stop losses do not work
112 | force_open=True,
113 | guaranteed_stop=guaranteed_stop,
114 | stop_distance=stop_distance,
115 | size=size,
116 | trailing_stop=trailing_stop,
117 | trailing_stop_increment=trailing_stop_increment,
118 | # trailing_stop_distance = trailing_stop_distance,
119 | # time_in_force=time_in_force,
120 | order_type=order_type,
121 | limit_distance=limit_distance)
122 |
123 | return response
124 | except Exception as e:
125 | self.log.info(str(e) + " error occurred when opening a position")
126 | return None
127 |
128 | # market orders to close positions
129 | def close_open_position(self, position, size):
130 | # set randomly
131 | try:
132 | direction = "BUY"
133 | position_direction = position["direction"]
134 | if position_direction == "BUY":
135 | direction = "SELL"
136 |
137 | deal_id = position["dealId"]
138 | order_type = "MARKET"
139 | size = size
140 |
141 | response = self.ig_service.close_open_position(
142 | deal_id=deal_id,
143 | direction=direction,
144 | order_type=order_type,
145 | size=size)
146 |
147 | return response
148 | except Exception as e:
149 | self.log.info(str(e) + " error occurred when closing position")
150 | return None
151 |
152 | def delete_working_order(self, deal_id):
153 | try:
154 | deal_id = deal_id
155 | response = self.ig_service.delete_working_order(deal_id)
156 | return response
157 | except Exception as e:
158 | self.log.info(str(e) + " error occurred when deleting working order")
159 | return None
160 |
161 |
162 | def update_position(self, limit_level, stop_level, deal_id, guaranteed_stop):
163 | limit_level = limit_level
164 | guaranteed_stop = guaranteed_stop
165 | stop_level=stop_level
166 | deal_id=deal_id
167 | trailing_stop = False
168 | trailing_stop_distance = None
169 | trailing_stop_increment = None
170 |
171 | try:
172 |
173 | response = self.ig_service.update_open_position(
174 | limit_level=limit_level,
175 | stop_level=stop_level,
176 | # guaranteed_stop=guaranteed_stop,
177 | deal_id =deal_id,
178 | # trailing_stop=trailing_stop,
179 | # trailing_stop_distance=trailing_stop_distance,
180 | # trailing_stop_increment=trailing_stop_increment
181 | )
182 |
183 | return response
184 |
185 | except Exception as e:
186 | self.log.info(str(e) + " error occurred when updating position or maybe the order is no longer open")
187 | return None
188 |
189 | def get_open_positions(self):
190 | while(True):
191 | try:
192 | return self.ig_service.fetch_open_positions()
193 | except Exception as e:
194 | self.log.info(str(e) + " error occurred when getting open positions")
195 | # resets the connection
196 | self.initialise_connection()
197 |
198 |
199 | def get_working_orders(self):
200 | while(True):
201 | try:
202 | return self.ig_service.fetch_working_orders()
203 | except Exception as e:
204 | self.log.info(str(e) + " error occurred when getting working orders")
205 | self.initialise_connection()
206 |
--------------------------------------------------------------------------------
/management_of_position/position_management.py:
--------------------------------------------------------------------------------
1 | from trading_ig import IGService
2 | from trading_ig.config import config
3 | import logging
4 |
5 | logger = logging.getLogger(__name__)
6 | logger.setLevel(logging.DEBUG)
7 |
8 | # if you need to cache to DB your requests
9 | from datetime import timedelta
10 | import requests_cache
11 |
12 | import time
13 | import json
14 | import math
15 | import pandas as pd
16 | from predefined_functions.initialisation import Initialisation
17 |
18 | class Position_Management():
19 | def __init__(self):
20 | # set object then connection
21 | self.initial = Initialisation()
22 | self.initialise_connection()
23 | self.initialise_data()
24 |
25 | def initialise_connection(self):
26 | self.ig_service = self.initial.initialise_connection()
27 |
28 | def initialise_data(self):
29 | # this should change to be more dynamic
30 | # self.instrument_data = pd.read_csv("D:/Data/IG_Data/instruments_new_filtered.csv")
31 | # self.instrument_data.drop("Unnamed: 0", axis=1, inplace=True)
32 | pass
33 |
34 | def initialise(self):
35 | logging.basicConfig(level=logging.DEBUG)
36 |
37 | expire_after = timedelta(hours=1)
38 | session = requests_cache.CachedSession(
39 | cache_name='cache', backend='sqlite', expire_after=expire_after
40 | )
41 | # set expire_after=None if you don't want cache expiration
42 | # set expire_after=0 if you don't want to cache queries
43 |
44 | # config = IGServiceConfig()
45 |
46 | # no cache
47 | self.ig_service = IGService(
48 | config.username, config.password, config.api_key, config.acc_type
49 | )
50 | # if you want to globally cache queries
51 | # ig_service = IGService(config.username, config.password, config.api_key, config.acc_type, session)
52 | self.ig_service.create_session()
53 |
54 | def get_margin_min_distance_from_position_stop(self, dealing_rules, current_price, guaranteed_stop):
55 | # for controlled risk, guaranteed stop loss thing - keep to this one - worst case scenario -
56 | if guaranteed_stop:
57 | map_of_items = dealing_rules["minControlledRiskStopDistance"]
58 | else:
59 | #normal stop loss
60 | map_of_items = dealing_rules["minNormalStopOrLimitDistance"]
61 |
62 | # single_row = self.instrument_data[self.instrument_data["epic"] == epic]
63 | # the mam produces back the actual value and not the dataframe
64 | # map_of_items = json.loads(single_row["minControlledRiskStopDistance"].max())
65 |
66 | difference_required = map_of_items["value"]
67 | # otherwise the unit is POINTS
68 | if map_of_items["unit"] == "PERCENTAGE":
69 | difference_required = difference_required / 100
70 | return (difference_required)*current_price
71 |
72 | return difference_required
73 |
74 | def get_margin_min_max_distance_from_position_limit(self, dealing_rules, current_price, min_limit_stop):
75 | # for controlled risk, guaranteed stop loss thing - keep to this one - worst case scenario
76 | if min_limit_stop:
77 | map_of_items = dealing_rules["minNormalStopOrLimitDistance"]
78 | else:
79 | map_of_items = dealing_rules["maxStopOrLimitDistance"]
80 |
81 | # single_row = self.instrument_data[self.instrument_data["epic"] == epic]
82 | # the mam produces back the actual value and not the dataframe
83 | # map_of_items = json.loads(single_row["minControlledRiskStopDistance"].max())
84 |
85 | difference_required = map_of_items["value"]
86 | # otherwise the unit is POINTS
87 | if map_of_items["unit"] == "PERCENTAGE":
88 | difference_required = difference_required / 100
89 | return (difference_required)*current_price
90 |
91 | return difference_required
92 |
93 |
94 | def is_new_levels_better_and_generate(self, direction,stop_distance, current_price, entered_price, limit_distance, local, old_stop_level_price=None):
95 | stop_level = 0
96 | limit_level = 0
97 | # going short
98 | if direction == "SELL":
99 | # unlikely as we would always have a stop loss
100 | if old_stop_level_price == None:
101 | # have to do this as the stop level might not work spread moving too quickly
102 | stop_level = current_price + (stop_distance * 10)
103 | limit_level = entered_price - limit_distance
104 |
105 | return stop_level, limit_level
106 |
107 | # can't do this as the price might miss the stop loss
108 | # --------------------------------------------------------------------------------
109 | # # setting the stop price at the entry point - as we are in profit
110 | # elif (current_price < entered_price) and (old_stop_level_price > entered_price):
111 | # return entered_price, None
112 | # --------------------------------------------------------------------------------
113 |
114 | # get the distance between the edge that we can place the stop loss and the old stop loss and meet it half way
115 | """
116 | This way you stop loss will that edge very closely
117 | """
118 |
119 | stop_loss_edge = current_price + stop_distance
120 | half_distance = (old_stop_level_price - stop_loss_edge)/2.0
121 | stop_level = current_price + half_distance
122 | # stop loss is being missed on exchange increasing value
123 | if old_stop_level_price > (stop_level+0.1):
124 | return stop_level , None
125 |
126 | return None
127 | else:
128 |
129 | # put the stop loss at the entered price
130 | if (old_stop_level_price == None) :
131 | stop_level = current_price - (stop_distance * 10)
132 | limit_level = entered_price + limit_distance
133 |
134 | return stop_level, limit_level
135 | # # we are in profit - put the stop loss on the entered price
136 | # ---------------------------------------------------------------------------------
137 | # elif (current_price > entered_price) and (old_stop_level_price < entered_price):
138 | # return entered_price, None
139 | # ---------------------------------------------------------------------------------
140 | # get the distance between the edge that we can place the stop loss and the old stop loss and meet it half way
141 | """
142 | This way you stop loss will that edge very closely
143 | """
144 | stop_loss_edge = current_price - stop_distance
145 | half_distance = (stop_loss_edge - old_stop_level_price)/2.0
146 | stop_level = current_price - half_distance
147 | # stop_loss is missing on exchange
148 | if old_stop_level_price < (stop_level - 0.1):
149 | return stop_level, None
150 |
151 | return None
152 |
153 | # generated stop loss levels (numbers, not really implemented)
154 | def generate_levels_if_none_exists(self, direction, stop_distance, current_price, entered_price, limit_distance):
155 | stop_level = 0
156 | limit_level = 0
157 | if direction == "SELL":
158 | stop_level = stop_distance + current_price
159 | limit_level = entered_price - limit_distance
160 | return stop_level,limit_level
161 |
162 | else:
163 | stop_level = stop_distance - current_price
164 | limit_level = entered_price + limit_distance
165 | return stop_level,limit_level
166 |
--------------------------------------------------------------------------------
/tests/data/historic_prices_v2.json:
--------------------------------------------------------------------------------
1 | {
2 | "prices": [
3 | {
4 | "snapshotTime": "2020/10/09 05:00:00",
5 | "openPrice": {
6 | "bid": 1915.5,
7 | "ask": 1916.1,
8 | "lastTraded": null
9 | },
10 | "closePrice": {
11 | "bid": 1936.3,
12 | "ask": 1936.3,
13 | "lastTraded": null
14 | },
15 | "highPrice": {
16 | "bid": 1936.4,
17 | "ask": 1937.0,
18 | "lastTraded": null
19 | },
20 | "lowPrice": {
21 | "bid": 1910.2,
22 | "ask": 1910.8,
23 | "lastTraded": null
24 | },
25 | "lastTradedVolume": 138981
26 | },
27 | {
28 | "snapshotTime": "2020/10/11 05:00:00",
29 | "openPrice": {
30 | "bid": 1926.2,
31 | "ask": 1926.2,
32 | "lastTraded": null
33 | },
34 | "closePrice": {
35 | "bid": 1933.2,
36 | "ask": 1933.8,
37 | "lastTraded": null
38 | },
39 | "highPrice": {
40 | "bid": 1939.1,
41 | "ask": 1939.7,
42 | "lastTraded": null
43 | },
44 | "lowPrice": {
45 | "bid": 1926.2,
46 | "ask": 1926.2,
47 | "lastTraded": null
48 | },
49 | "lastTradedVolume": 25069
50 | },
51 | {
52 | "snapshotTime": "2020/10/12 05:00:00",
53 | "openPrice": {
54 | "bid": 1933.4,
55 | "ask": 1934.0,
56 | "lastTraded": null
57 | },
58 | "closePrice": {
59 | "bid": 1916.0,
60 | "ask": 1916.6,
61 | "lastTraded": null
62 | },
63 | "highPrice": {
64 | "bid": 1937.7,
65 | "ask": 1938.3,
66 | "lastTraded": null
67 | },
68 | "lowPrice": {
69 | "bid": 1915.1,
70 | "ask": 1915.7,
71 | "lastTraded": null
72 | },
73 | "lastTradedVolume": 117691
74 | },
75 | {
76 | "snapshotTime": "2020/10/13 05:00:00",
77 | "openPrice": {
78 | "bid": 1915.9,
79 | "ask": 1916.5,
80 | "lastTraded": null
81 | },
82 | "closePrice": {
83 | "bid": 1898.5,
84 | "ask": 1899.1,
85 | "lastTraded": null
86 | },
87 | "highPrice": {
88 | "bid": 1930.2,
89 | "ask": 1930.8,
90 | "lastTraded": null
91 | },
92 | "lowPrice": {
93 | "bid": 1884.8,
94 | "ask": 1885.4,
95 | "lastTraded": null
96 | },
97 | "lastTradedVolume": 182974
98 | },
99 | {
100 | "snapshotTime": "2020/10/14 05:00:00",
101 | "openPrice": {
102 | "bid": 1898.6,
103 | "ask": 1899.2,
104 | "lastTraded": null
105 | },
106 | "closePrice": {
107 | "bid": 1901.5,
108 | "ask": 1902.1,
109 | "lastTraded": null
110 | },
111 | "highPrice": {
112 | "bid": 1917.2,
113 | "ask": 1917.8,
114 | "lastTraded": null
115 | },
116 | "lowPrice": {
117 | "bid": 1895.4,
118 | "ask": 1896.0,
119 | "lastTraded": null
120 | },
121 | "lastTradedVolume": 136388
122 | },
123 | {
124 | "snapshotTime": "2020/10/15 05:00:00",
125 | "openPrice": {
126 | "bid": 1901.4,
127 | "ask": 1902.0,
128 | "lastTraded": null
129 | },
130 | "closePrice": {
131 | "bid": 1909.8,
132 | "ask": 1910.4,
133 | "lastTraded": null
134 | },
135 | "highPrice": {
136 | "bid": 1914.9,
137 | "ask": 1915.5,
138 | "lastTraded": null
139 | },
140 | "lowPrice": {
141 | "bid": 1892.6,
142 | "ask": 1893.2,
143 | "lastTraded": null
144 | },
145 | "lastTradedVolume": 149438
146 | },
147 | {
148 | "snapshotTime": "2020/10/16 05:00:00",
149 | "openPrice": {
150 | "bid": 1909.9,
151 | "ask": 1910.5,
152 | "lastTraded": null
153 | },
154 | "closePrice": {
155 | "bid": 1902.9,
156 | "ask": 1902.9,
157 | "lastTraded": null
158 | },
159 | "highPrice": {
160 | "bid": 1918.4,
161 | "ask": 1919.0,
162 | "lastTraded": null
163 | },
164 | "lowPrice": {
165 | "bid": 1900.9,
166 | "ask": 1901.5,
167 | "lastTraded": null
168 | },
169 | "lastTradedVolume": 96594
170 | },
171 | {
172 | "snapshotTime": "2020/10/18 05:00:00",
173 | "openPrice": {
174 | "bid": 1906.4,
175 | "ask": 1906.4,
176 | "lastTraded": null
177 | },
178 | "closePrice": {
179 | "bid": 1903.6,
180 | "ask": 1904.2,
181 | "lastTraded": null
182 | },
183 | "highPrice": {
184 | "bid": 1906.4,
185 | "ask": 1906.9,
186 | "lastTraded": null
187 | },
188 | "lowPrice": {
189 | "bid": 1900.0,
190 | "ask": 1900.6,
191 | "lastTraded": null
192 | },
193 | "lastTradedVolume": 14182
194 | },
195 | {
196 | "snapshotTime": "2020/10/19 05:00:00",
197 | "openPrice": {
198 | "bid": 1903.5,
199 | "ask": 1904.1,
200 | "lastTraded": null
201 | },
202 | "closePrice": {
203 | "bid": 1903.7,
204 | "ask": 1904.3,
205 | "lastTraded": null
206 | },
207 | "highPrice": {
208 | "bid": 1922.5,
209 | "ask": 1923.1,
210 | "lastTraded": null
211 | },
212 | "lowPrice": {
213 | "bid": 1896.5,
214 | "ask": 1897.1,
215 | "lastTraded": null
216 | },
217 | "lastTradedVolume": 123866
218 | },
219 | {
220 | "snapshotTime": "2020/10/20 05:00:00",
221 | "openPrice": {
222 | "bid": 1903.6,
223 | "ask": 1904.2,
224 | "lastTraded": null
225 | },
226 | "closePrice": {
227 | "bid": 1909.4,
228 | "ask": 1909.4,
229 | "lastTraded": null
230 | },
231 | "highPrice": {
232 | "bid": 1917.4,
233 | "ask": 1918.0,
234 | "lastTraded": null
235 | },
236 | "lowPrice": {
237 | "bid": 1899.7,
238 | "ask": 1900.3,
239 | "lastTraded": null
240 | },
241 | "lastTradedVolume": 103956
242 | }
243 | ],
244 | "instrumentType": "COMMODITIES",
245 | "allowance": {
246 | "remainingAllowance": 9698,
247 | "totalAllowance": 10000,
248 | "allowanceExpiry": 273984
249 | }
250 | }
--------------------------------------------------------------------------------
/getting_historical_data/rest_ig_get_historical_data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | """
5 | IG Markets REST API sample with Python
6 | 2015 FemtoTrader
7 | """
8 |
9 | from trading_ig import IGService
10 | from trading_ig.config import config
11 | import logging
12 | import pandas as pd
13 | import os
14 |
15 | logger = logging.getLogger(__name__)
16 | logger.setLevel(logging.DEBUG)
17 |
18 | # if you need to cache to DB your requests
19 | from datetime import datetime, timedelta
20 | import requests_cache
21 | import math
22 | import numpy as np
23 | import time
24 |
25 | counter = -1
26 |
27 |
28 | def login():
29 | expire_after = timedelta(hours=1)
30 | session = requests_cache.CachedSession(
31 | cache_name='cache', backend='sqlite', expire_after=expire_after
32 | )
33 | api_key = increment_api_key()
34 |
35 | # no cache
36 | ig_service = IGService(
37 | config.username, config.password, api_key, config.acc_type
38 | )
39 | ig_service.create_session()
40 |
41 | return ig_service
42 |
43 |
44 | def main():
45 | logging.basicConfig(level=logging.DEBUG)
46 | #
47 | # expire_after = timedelta(hours=1)
48 | # session = requests_cache.CachedSession(
49 | # cache_name='cache', backend='sqlite', expire_after=expire_after
50 | # )
51 | # # set expire_after=None if you don't want cache expiration
52 | # # set expire_after=0 if you don't want to cache queries
53 | #
54 | # #config = IGServiceConfig()
55 | #
56 | # # no cache
57 | # ig_service = IGService(
58 | # config.username, config.password, config.api_key, config.acc_type
59 | # )
60 | #
61 | # # if you want to globally cache queries
62 | # #ig_service = IGService(config.username, config.password, config.api_key, config.acc_type, session)
63 | #
64 | # ig_service.create_session()
65 |
66 | # accounts = ig_service.fetch_accounts()
67 | # print("accounts:\n%s" % accounts)
68 |
69 | # account_info = ig_service.switch_account(config.acc_number, False)
70 | # print(account_info)
71 |
72 | # open_positions = ig_service.fetch_open_positions()
73 | # print("open_positions:\n%s" % open_positions)
74 |
75 | ig_service = login()
76 |
77 | print("")
78 |
79 | # working_orders = ig_service.fetch_working_orders()
80 | # print("working_orders:\n%s" % working_orders)
81 |
82 | print("")
83 |
84 | # strimming data ----------------------
85 | # instrument_data = pd.read_csv("D:/Data/IG_Data/instruments.csv")
86 | # instrument_data.drop("Unnamed: 0", axis=1, inplace=True)
87 | #
88 | # instrument_data["average"] = (instrument_data["bid"] + instrument_data["offer"]) / 2
89 | # instrument_data["margin_in_pounds_required"] = instrument_data["average"] * 0.5 * instrument_data["margin"]
90 | #
91 | # # Cheap_Shares = instrument_data[(instrument_data["margin_in_pounds_required"] < 2)
92 | # # & (instrument_data["location"].str.contains("Shares - ")
93 | # # & (instrument_data["margin_in_pounds_required"] > 1))]
94 | #
95 | # # Cheap_Shares = instrument_data[(instrument_data["margin_in_pounds_required"] < 10)
96 | # # & (instrument_data["location"].str.contains("Shares - ")
97 | # # & (instrument_data["average"] > 1))]
98 | #
99 | # # gets rid of small averages
100 | # # gets rid of small averages
101 | # list_of_items_to_remove = []
102 | # for index in range(instrument_data.index.size):
103 | # # print(instrument_data["average"].iloc[index])
104 | #
105 | # if (instrument_data["average"].iloc[index] < 0.5) or (math.isnan(instrument_data["average"].iloc[index]) or (
106 | # instrument_data["location"].str.contains("Option").iloc[index])):
107 | # list_of_items_to_remove.append(instrument_data.index[index])
108 | #
109 | # for item in list_of_items_to_remove:
110 | # instrument_data.drop(index=item, axis=0, inplace=True)
111 | # strimming data ----------------------
112 |
113 | instrument = pd.read_csv("D:/Stock_Analysis/ig-markets-api-python-library-master/Data/SpreadBetting/Instruments.csv")
114 | instrument.drop("Unnamed: 0", axis=1, inplace=True)
115 |
116 | list_of_epics = instrument["epic"].to_list()
117 | list_names = instrument["name"].to_list()
118 |
119 |
120 | resolution = '5Min'
121 |
122 |
123 | for date_counter in range(1):
124 |
125 | # start_date = "2020-11-%02d" % date_counter
126 | # end_date = "2020-11-%02d" % (date_counter + 1)
127 | start_date = "2021-05-10"
128 | end_date = "2021-05-12"
129 |
130 | for index in range(len(list_of_epics)):
131 |
132 | epic = list_of_epics[index]
133 | name = list_names[index]
134 | # epic = 'CS.D.EURUSD.MINI.IP'
135 | # epic = 'IX.D.ASX.IFM.IP' # US (SPY) - mini
136 |
137 | # resolution = 'D'
138 | # see from pandas.tseries.frequencies import to_offset
139 | # resolution = 'H'
140 | # resolution = '1Min'
141 |
142 | num_points = 9000
143 | print(name)
144 | response = None
145 |
146 | while (True):
147 | try:
148 | # response = ig_service.fetch_historical_prices_by_epic_and_num_points(
149 | # epic, resolution, num_points
150 | # )
151 | response = ig_service.fetch_historical_prices_by_epic_and_date_range(
152 | epic=epic, resolution=resolution, start_date=start_date, end_date=end_date
153 | )
154 | break
155 | except Exception as e:
156 | print(e, " there was not data available")
157 |
158 | if (str(e) == "error.public-api.exceeded-account-historical-data-allowance") or (str(e) == "error.security.client-token-invalid") or (str(e) == "error.security.generic") or (str(e) == "error.public-api.exceeded-api-key-allowance"):
159 | ig_service = login()
160 | continue
161 | else:
162 | print(e, "exception not know")
163 |
164 | break
165 |
166 | if response == None:
167 | continue
168 |
169 | print(response)
170 | print("\n \n")
171 | data_frame_of_prices = response["prices"]
172 | save_to_file(data_frame_of_prices, name,resolution, start_date, end_date,epic)
173 |
174 |
175 |
176 |
177 | def save_to_file(dataframe, name, resolution, start_date, end_date, epic):
178 |
179 | try:
180 | name = name.replace("/", "-")
181 | directory = r"D:/Data/IG_Instrument/historical_data/"+resolution+"/"+start_date+"_"+end_date
182 | if not os.path.exists(directory):
183 | try:
184 | semi_directory = r"D:/Data/IG_Instrument/historical_data/"+resolution
185 | os.mkdir(semi_directory)
186 | except Exception as e:
187 | print(e)
188 |
189 | os.mkdir(directory)
190 |
191 | full_path = directory+"/"+name+"_"+resolution+"_ID_"+epic+"_ID_.csv"
192 |
193 | dataframe.to_csv(full_path)
194 | except Exception as e:
195 | print("failed to write to file " + str(e))
196 |
197 |
198 |
199 | def increment_api_key():
200 | key = ""
201 | global counter
202 | flag = True
203 | while (flag):
204 | try:
205 | counter += 1
206 | # has 12000 api keys
207 | fp = open("D:/Stock_Analysis/ig-markets-api-python-library-master/generate_api_keys/IG_api_keys_raw.txt")
208 | for i, line in enumerate(fp):
209 | if i == counter:
210 | key = line.split("\n")[0]
211 | flag = False
212 | break
213 |
214 | fp.close()
215 | except:
216 | counter = -1
217 |
218 | return key
219 |
220 |
221 | if __name__ == '__main__':
222 | main()
223 |
--------------------------------------------------------------------------------
/Data/CFDs/instrument_details_SECTORS.csv:
--------------------------------------------------------------------------------
1 | bid,delayTime,epic,expiry,high,instrumentName,instrumentType,lotSize,low,marketStatus,netChange,offer,otcTradeable,percentageChange,scalingFactor,streamingPricesAvailable,updateTime,updateTimeUTC1286.9,0,KB.D.OZTELE.IFD.IP,-,1295.3,Australia 200 Communications,SECTORS,10,1272.5,TRADEABLE,20.4,1292.1,True,1.61,1,True,-1705000,00:31:35
2 | 1286.9,0,KB.D.OZTELE.IFM.IP,-,1295.3,Australia 200 Communications (A$2 Mini Contract),SECTORS,2,1272.5,TRADEABLE,20.4,1292.1,True,1.61,1,True,-1705000,00:31:35
3 | 2734.2,0,KB.D.OZCOND.IFD.IP,-,2748.3,Consumer Disc.,SECTORS,10,2721.3,TRADEABLE,13.7,2745.2,True,0.5,1,True,-1675000,00:32:05
4 | 2734.2,0,KB.D.OZCOND.IFM.IP,-,2748.3,Consumer Disc. (A$2 Mini Contract),SECTORS,2,2721.3,TRADEABLE,13.7,2745.2,True,0.5,1,True,-1675000,00:32:05
5 | 13169.3,0,KB.D.OZCONSUM.IFD.IP,-,13235.0,Consumer Staples,SECTORS,10,13140.5,TRADEABLE,50.7,13222.1,True,0.39,1,True,-1675000,00:32:05
6 | 13169.3,0,KB.D.OZCONSUM.IFM.IP,-,13235.0,Consumer Staples (A$2 Mini Contract),SECTORS,2,13140.5,TRADEABLE,50.7,13222.1,True,0.39,1,True,-1675000,00:32:05
7 | 11540.6,0,KB.D.OZENER.IFD.IP,-,11612.7,Energy,SECTORS,10,11466.0,TRADEABLE,37.1,11586.8,True,0.32,1,True,-1675000,00:32:05
8 | 11540.6,0,KB.D.OZENER.IFM.IP,-,11612.7,Energy (A$2 Mini Contract),SECTORS,2,11466.0,TRADEABLE,37.1,11586.8,True,0.32,1,True,-1675000,00:32:05
9 | 6061.5,0,KB.D.OZFINL.IFD.IP,-,6091.0,Financials,SECTORS,10,6041.5,TRADEABLE,5.4,6085.7,True,0.09,1,True,-1675000,00:32:05
10 | 6061.5,0,KB.D.OZFINL.IFM.IP,-,6091.0,Financials (A$2 Mini Contract),SECTORS,2,6041.5,TRADEABLE,5.4,6085.7,True,0.09,1,True,-1675000,00:32:05
11 | 41228.1,0,KB.D.OZHEALTH.IFD.IP,-,41421.6,Health,SECTORS,10,40984.4,TRADEABLE,3.0,41393.3,True,0.01,1,True,-1675000,00:32:05
12 | 41228.1,0,KB.D.OZHEALTH.IFM.IP,-,41421.6,Health (A$2 Mini Contract),SECTORS,2,40984.4,TRADEABLE,3.0,41393.3,True,0.01,1,True,-1675000,00:32:05
13 | 7175.8,0,KB.D.OZINDU.IFD.IP,-,7218.0,Industrials,SECTORS,10,7171.7,TRADEABLE,1.1,7204.6,True,0.02,1,True,-1675000,00:32:05
14 | 7175.8,0,KB.D.OZINDU.IFM.IP,-,7218.0,Industrials (A$2 Mini Contract),SECTORS,2,7171.7,TRADEABLE,1.1,7204.6,True,0.02,1,True,-1675000,00:32:05
15 | 1451.3,0,KB.D.OZIT.IFD.IP,-,1457.1,IT,SECTORS,10,1443.1,TRADEABLE,9.2,1457.1,True,0.64,1,True,-1645000,00:32:35
16 | 1451.3,0,KB.D.OZIT.IFM.IP,-,1457.1,IT (A$2 Mini Contract),SECTORS,2,1443.1,TRADEABLE,9.2,1457.1,True,0.64,1,True,-1645000,00:32:35
17 | 13584.7,0,KB.D.OZMATR.IFD.IP,-,13656.1,Materials,SECTORS,10,13526.1,TRADEABLE,111.5,13639.1,True,0.83,1,True,-1615000,00:33:05
18 | 13584.7,0,KB.D.OZMATR.IFM.IP,-,13656.1,Materials (A$2 Mini Contract),SECTORS,2,13526.1,TRADEABLE,111.5,13639.1,True,0.83,1,True,-1615000,00:33:05
19 | 8147.4,0,KB.D.OZUTILI.IFD.IP,-,8200.5,Utilities,SECTORS,10,8112.1,TRADEABLE,89.9,8180.0,True,1.11,1,True,-1615000,00:33:05
20 | 8147.4,0,KB.D.OZUTILI.IFM.IP,-,8200.5,Utilities (A$2 Mini Contract),SECTORS,2,8112.1,TRADEABLE,89.9,8180.0,True,1.11,1,True,-1615000,00:33:05
21 | 5092.0,0,KB.D.AERO.CASH.IP,-,5116.0,Aerospace and Defence,SECTORS,10,5072.0,EDITS_ONLY,-2.0,5102.0,True,-0.04,1,True,55800000,16:30:00
22 | 3689.0,0,KB.D.BANKS.CASH.IP,-,3706.0,Banks,SECTORS,10,3672.0,EDITS_ONLY,6.0,3697.0,True,0.15,1,True,56129000,16:35:29
23 | 3689.0,0,KB.D.BANKS.IFM.IP,-,3706.0,Banks (£2 Mini Contract),SECTORS,2,3672.0,EDITS_ONLY,6.0,3697.0,True,0.15,1,True,56129000,16:35:29
24 | 25369.0,0,KB.D.DRINKS.CASH.IP,-,25528.0,Beverages,SECTORS,10,25107.0,EDITS_ONLY,317.0,25419.0,True,1.26,1,True,56126000,16:35:26
25 | 13006.0,0,KB.D.CHEMS.CASH.IP,-,12999.0,Chemicals,SECTORS,10,12767.0,EDITS_ONLY,255.0,13032.0,True,2.0,1,True,56128000,16:35:28
26 | 6906.0,0,KB.D.BUILD.CASH.IP,-,6933.0,Construction and Materials,SECTORS,10,6817.0,EDITS_ONLY,169.0,6920.0,True,2.5,1,True,56125000,16:35:25
27 | 7717.0,0,KB.D.ELECTY.CASH.IP,-,7834.0,Electricity,SECTORS,10,7736.0,EDITS_ONLY,-89.0,7732.0,True,-1.14,1,True,56129000,16:35:29
28 | 8622.0,0,KB.D.EE.CASH.IP,-,8644.0,Electronic and Electrical Equipment,SECTORS,10,8451.0,EDITS_ONLY,162.0,8639.0,True,1.92,1,True,56115000,16:35:15
29 | 10573.0,0,KB.D.INV.CASH.IP,-,10579.0,Equity Investment Instruments,SECTORS,10,10519.0,EDITS_ONLY,62.0,10595.0,True,0.59,1,True,56437000,16:40:37
30 | 12119.0,0,KB.D.SPECFINAN.CASH.IP,-,12156.0,Financial Services,SECTORS,10,11999.0,EDITS_ONLY,168.0,12143.0,True,1.41,1,True,56130000,16:35:30
31 | 2222.0,0,KB.D.PHONES.CASH.IP,-,2253.0,Fixed Line Telecommunications,SECTORS,10,2222.0,EDITS_ONLY,-29.0,2227.0,True,-1.27,1,True,56121000,16:35:21
32 | 3870.0,0,KB.D.FDR.CASH.IP,-,3894.0,Food and Drug Retailers,SECTORS,10,3863.0,EDITS_ONLY,-1.0,3878.0,True,-0.03,1,True,56126000,16:35:26
33 | 7931.0,0,KB.D.FOOD.CASH.IP,-,7953.0,Food Producers,SECTORS,10,7775.0,EDITS_ONLY,123.0,7947.0,True,1.58,1,True,56129000,16:35:29
34 | 5108.0,0,KB.D.WATER.CASH.IP,-,5157.0,Gas Water and Multiutilities,SECTORS,10,5106.0,EDITS_ONLY,0.0,5118.0,True,-0.0,1,True,56121000,16:35:21
35 | 6220.0,0,KB.D.GINDU.CASH.IP,-,6265.0,General Industrials,SECTORS,10,6188.0,EDITS_ONLY,15.0,6232.0,True,0.24,1,True,56127000,16:35:27
36 | 6220.0,0,KB.D.GINDU.IFM.IP,-,6265.0,General Industrials (£2 Mini Contract),SECTORS,10,6188.0,EDITS_ONLY,15.0,6232.0,True,0.24,1,True,56127000,16:35:27
37 | 2331.0,0,KB.D.RETAIL.CASH.IP,-,2347.0,General Retailers,SECTORS,10,2327.0,EDITS_ONLY,10.0,2336.0,True,0.43,1,True,56130000,16:35:30
38 | 2331.0,0,KB.D.RETAIL.IFM.IP,-,2347.0,General Retailers (£2 Mini Contract),SECTORS,2,2327.0,EDITS_ONLY,10.0,2336.0,True,0.43,1,True,56130000,16:35:30
39 | 8213.0,0,KB.D.HEALTH.CASH.IP,-,8262.0,Health Care Equipment and Services,SECTORS,10,8127.0,EDITS_ONLY,2.0,8229.0,True,0.02,1,True,56129000,16:35:29
40 | 17005.0,0,KB.D.HSEHLD.CASH.IP,-,17096.0,Household Goods and Home Construction,SECTORS,10,16928.0,EDITS_ONLY,135.0,17039.0,True,0.8,1,True,55800000,16:30:00
41 | 20844.0,0,KB.D.MID250.CASH.IP,-,20885.0,FTSE Mid 250,SECTORS,10,20697.0,EDITS_ONLY,162.0,20886.0,True,0.78,1,True,56437000,16:40:37
42 | 20844.0,0,KB.D.MID250.IFM.IP,-,20885.0,FTSE Mid 250 (£2 Mini Contract),SECTORS,2,20697.0,EDITS_ONLY,162.0,20886.0,True,0.78,1,True,56437000,16:40:37
43 | 5768.0,0,KB.D.TK.CASH.IP,-,5789.0,Techmark,SECTORS,10,5727.0,EDITS_ONLY,34.0,5779.0,True,0.59,1,True,56129000,16:35:29
44 | 5768.0,0,KB.D.TK.IFM.IP,-,5789.0,Techmark (£2 Mini Contract),SECTORS,2,5727.0,EDITS_ONLY,34.0,5779.0,True,0.59,1,True,56129000,16:35:29
45 | 13104.0,0,KB.D.ENGINE.CASH.IP,-,13166.0,Industrial Engineering,SECTORS,10,12966.0,EDITS_ONLY,118.0,13130.0,True,0.91,1,True,56129000,16:35:29
46 | 2365.0,0,KB.D.BUS.CASH.IP,-,2383.0,Industrial Transportation,SECTORS,10,2317.0,EDITS_ONLY,56.0,2370.0,True,2.4,1,True,56118000,16:35:18
47 | 7538.0,0,KB.D.LIFE.CASH.IP,-,7570.0,Life Insurance,SECTORS,10,7484.0,EDITS_ONLY,23.0,7553.0,True,0.3,1,True,56125000,16:35:25
48 | 8810.0,0,KB.D.MEDIA.CASH.IP,-,8865.0,Media,SECTORS,10,8799.0,EDITS_ONLY,6.0,8828.0,True,0.07,1,True,56130000,16:35:30
49 | 18531.0,0,KB.D.MINING.CASH.IP,-,18595.0,Mining,SECTORS,10,18419.0,EDITS_ONLY,129.0,18568.0,True,0.7,1,True,56128000,16:35:28
50 | 18531.0,0,KB.D.MINING.IFM.IP,-,18595.0,Mining (£2 Mini Contract),SECTORS,2,18419.0,EDITS_ONLY,129.0,18568.0,True,0.7,1,True,56128000,16:35:28
51 | 3101.0,0,KB.D.INSURANCE.CASH.IP,-,3104.0,Non-life Insurance,SECTORS,10,3057.0,EDITS_ONLY,50.0,3107.0,True,1.65,1,True,56121000,16:35:21
52 | 8230.0,0,KB.D.OIL.CASH.IP,-,8368.0,Oil and Gas Producers,SECTORS,10,8225.0,EDITS_ONLY,-100.0,8246.0,True,-1.2,1,True,56115000,16:35:15
53 | 7953.0,0,KB.D.OILEQUIP.CASH.IP,-,8226.0,Oil Equipment and Services,SECTORS,10,7885.0,EDITS_ONLY,-100.0,7969.0,True,-1.24,1,True,56123000,16:35:23
54 | 39261.31,0,KB.D.PGOODS.CASH.IP,-,39517.4,Personal Goods,SECTORS,10,38776.49,EDITS_ONLY,328.9,39339.91,True,0.84,1,True,56124000,16:35:24
55 | 17554.0,0,KB.D.PHARMA.IFM.IP,-,17612.0,Pharmaceuticals (£2 Mini Contract),SECTORS,2,17352.0,EDITS_ONLY,92.0,17607.0,True,0.53,1,True,56128000,16:35:28
56 | 17563.0,0,KB.D.PHARMA.CASH.IP,-,17603.0,Pharmaceuticals and Biotechnology,SECTORS,10,17361.0,EDITS_ONLY,92.0,17598.0,True,0.53,1,True,56128000,16:35:28
57 | 3208.0,0,KB.D.REAL.CASH.IP,-,3224.0,Real Estate Investment Trusts,SECTORS,10,3179.0,EDITS_ONLY,24.0,3214.0,True,0.76,1,True,56130000,16:35:30
58 | 2172.0,0,KB.D.SOFT.CASH.IP,-,2183.0,Software and Computer Services,SECTORS,10,2145.0,EDITS_ONLY,12.0,2176.0,True,0.55,1,True,56126000,16:35:26
59 | 9316.0,0,KB.D.SUPPORT.CASH.IP,-,9346.0,Support Services,SECTORS,10,9186.0,EDITS_ONLY,78.0,9334.0,True,0.85,1,True,56126000,16:35:26
60 | 31627.0,0,KB.D.TOBACCO.CASH.IP,-,31971.0,Tobacco,SECTORS,10,31541.0,EDITS_ONLY,-203.0,31690.0,True,-0.64,1,True,56121000,16:35:21
61 | 31627.0,0,KB.D.TOBACCO.IFM.IP,-,31971.0,Tobacco (£2 Mini Contract),SECTORS,2,31541.0,EDITS_ONLY,-203.0,31690.0,True,-0.64,1,True,56121000,16:35:21
62 | 10108.0,0,KB.D.HOTELS.CASH.IP,-,10189.0,Travel and Leisure,SECTORS,10,10036.0,EDITS_ONLY,-169.0,10128.0,True,-1.64,1,True,56124000,16:35:24
63 |
--------------------------------------------------------------------------------
/getting_realtime_data/data_retrieval.py:
--------------------------------------------------------------------------------
1 | import time
2 | import sys
3 | import traceback
4 | import logging
5 | import math
6 |
7 | from trading_ig import (IGService, IGStreamService)
8 | from trading_ig.config import config
9 | from trading_ig.lightstreamer import Subscription
10 | from predefined_functions.initialisation import Initialisation
11 |
12 | class Data_Retrieval:
13 | def __init__(self):
14 | logging.basicConfig(level=logging.INFO)
15 | self.log = logging.getLogger(__name__)
16 | self.ig_stream_service = []
17 | self.data_map = {}
18 | self.initial = Initialisation()
19 |
20 | def initialise_connection(self, number_of_subscriptions):
21 | # logging.basicConfig(level=logging.DEBUG)
22 | for index in range(number_of_subscriptions):
23 | while(True):
24 | try:
25 | ig_service = self.initial.initialise_connection()
26 |
27 | self.ig_stream_service.append(IGStreamService(ig_service))
28 | ig_session = self.ig_stream_service[index].create_session()
29 | self.accountId = config.acc_number
30 | self.ig_stream_service[index].connect(self.accountId)
31 | # it will automatically create the account connection
32 | break
33 | except Exception as e:
34 | print(e, " data retrieval error login")
35 |
36 |
37 | def restart_service(self):
38 | while(True):
39 | try:
40 | self.ig_stream_service.unsubscribe_all()
41 | self.initialise_connection()
42 | return
43 | except Exception as e:
44 | self.log.info(str(e) + " connection error")
45 |
46 |
47 | # market data based info
48 | def create_subscription_market_data(self, data):
49 | number_of_subscriptions = math.ceil(len(data)/30)
50 | if number_of_subscriptions > 38:
51 | raise Exception("your account could be blocked, too many subscriptions ")
52 | self.initialise_connection(number_of_subscriptions)
53 | list_of_epics_in_sets_30 = list(self.chunks(data, 30))
54 |
55 | for index in range(len(list_of_epics_in_sets_30)):
56 | self.create_individual_subscription_market_data(list_of_epics_in_sets_30[index], index)
57 |
58 |
59 | def chunks(self,lst, n):
60 | """Yield successive n-sized chunks from lst."""
61 | for i in range(0, len(lst), n):
62 | yield lst[i:i + n]
63 |
64 |
65 | def create_individual_subscription_market_data(self,data,index):
66 | # if len(self.ig_stream_service.ls_client._subscriptions) > 0:
67 | # #reset everything market data based
68 | # self.restart_service()
69 |
70 | subscription_holding = self.create_subscription_subPrice(data)
71 | self.ig_stream_service[index].ls_client.subscribe(subscription_holding)
72 |
73 |
74 | # account and trade based info
75 | def create_subscription_account(self):
76 | self.initialise_connection(1)
77 | subscription_holding = self.create_subscription_subAccount()
78 | self.ig_stream_service[0].ls_client.subscribe(subscription_holding)
79 |
80 | def create_subscription_trade(self):
81 | self.initialise_connection(1)
82 | subscription_holding = self.create_subscription_subTradeInfo()
83 | self.ig_stream_service[0].ls_client.subscribe(subscription_holding)
84 |
85 |
86 | # done like this for debugging purposes
87 | def register_subscription(self, subscription):
88 | sub_key_prices = self.ig_stream_service.ls_client.subscribe(subscription)
89 | return sub_key_prices
90 |
91 |
92 |
93 | # subscription functions
94 | def create_subscription_subAccount(self):
95 |
96 | subscription_account = Subscription(
97 | mode="MERGE",
98 | items=['ACCOUNT:' + self.accountId],
99 | fields=[
100 | "AVAILABLE_CASH",
101 | "PNL",
102 | "PNL_LR",
103 | "PNL_NLR",
104 | "FUNDS",
105 | "MARGIN",
106 | "MARGIN_LR",
107 | "AVAILABLE_TO_DEAL",
108 | "EQUITY",
109 | "EQUITY_USED"],
110 | )
111 |
112 | # #adapter="QUOTE_ADAPTER")
113 |
114 | # Adding the "on_balance_update" function to Subscription
115 | subscription_account.addlistener(self.on_account_update)
116 | return subscription_account
117 |
118 | def create_subscription_subTradeInfo(self):
119 |
120 | subscription_trade = Subscription(
121 |
122 | mode="DISTINCT",
123 | items=['TRADE:' + self.accountId],
124 | fields=[
125 | "CONFIRMS",
126 | "OPU",
127 | "WOU"],
128 | )
129 |
130 | subscription_trade.addlistener(self.on_trade_update)
131 | return subscription_trade
132 |
133 | def create_subscription_subPrice(self, epic_temp):
134 | # Making a new Subscription in MERGE mode
135 | epic_list = list.copy(epic_temp)
136 | for index in range(len(epic_list)):
137 | epic_list[index] = "L1:"+epic_list[index]
138 |
139 | subscription_prices = Subscription(
140 | mode="MERGE",
141 | items=epic_list,
142 | fields=["UPDATE_TIME",
143 | "BID",
144 | "OFFER",
145 | "CHANGE",
146 | "MARKET_STATE",
147 | "MID_OPEN",
148 | "HIGH",
149 | "LOW",
150 | "CHANGE",
151 | "CHANGE_PCT",
152 | "MARKET_DELAY"]
153 | )
154 | #
155 | # CHANGE_PCT
156 | # UPDATE_TIME
157 | # MARKET_DELAY Delayed price (0=false, 1=true)
158 | # MARKET_STATE
159 |
160 | subscription_prices.addlistener(self.on_prices_update)
161 | return subscription_prices
162 |
163 |
164 | # function to catch update in events
165 | def on_prices_update(self, item_update):
166 | # print("price: %s " % item_update)
167 | name = item_update["name"].split(":")[1]
168 |
169 | if not name in self.data_map:
170 | self.data_map[name] = []
171 | for items in item_update["values"]:
172 | try:
173 | item_update["values"][items] = float(item_update["values"][items])
174 | except:
175 | pass
176 |
177 | self.data_map[name].append(item_update["values"])
178 |
179 | if len(self.data_map[name]) > 20:
180 | # remove only keep the latest 20 items
181 | self.data_map[name] = self.data_map[name][-20:]
182 |
183 |
184 | # print("{stock_name:<19}: Time {UPDATE_TIME:<8} - "
185 | # "Bid {BID:>5} - Ask {OFFER:>5}".format(
186 | # stock_name=item_update["name"], **item_update["values"]
187 | # ))
188 |
189 | def on_account_update(self, balance_update):
190 | name = "account"
191 | if not name in self.data_map:
192 | self.data_map[name] = []
193 | self.data_map[name].append(balance_update)
194 |
195 | if len(self.data_map[name]) > 20:
196 | # remove only keep the latest 20 items
197 | self.data_map[name] = self.data_map[name][-20:]
198 |
199 | # print("balance: %s " % balance_update)
200 |
201 | def on_trade_update(self, trade_update):
202 | name = "trade"
203 | if not name in self.data_map:
204 | self.data_map[name] = []
205 | self.data_map[name].append(trade_update)
206 |
207 | if len(self.data_map[name]) > 20:
208 | # remove only keep the latest 20 items
209 | self.data_map[name] = self.data_map[name][-20:]
210 |
211 | # print("trade: %s " % trade_update)
212 |
213 |
214 | # get the latest data
215 | def get_market_data(self, epic):
216 | if epic in self.data_map:
217 | return self.data_map[epic][-1]
218 |
219 | def get_old_market_data(self, epic):
220 | if epic in self.data_map:
221 | if len(self.data_map[epic]) >= 19:
222 | return self.data_map[epic][0]
223 |
224 | def get_trade_data(self):
225 | if "trade" in self.data_map:
226 | return self.data_map["trade"][-1]
227 | else:
228 | return None
229 |
230 | def get_account_data(self):
231 | if "account" in self.data_map:
232 | return self.data_map["account"][-1]
233 | else:
234 | return None
--------------------------------------------------------------------------------
/tests/data/historic_prices.json:
--------------------------------------------------------------------------------
1 | {
2 | "prices": [
3 | {
4 | "snapshotTime": "2020/10/12 21:50:00",
5 | "snapshotTimeUTC": "2020-10-12T20:50:00",
6 | "openPrice": {
7 | "bid": 1926.4,
8 | "ask": 1927.0,
9 | "lastTraded": null
10 | },
11 | "closePrice": {
12 | "bid": 1927.3,
13 | "ask": 1927.9,
14 | "lastTraded": null
15 | },
16 | "highPrice": {
17 | "bid": 1927.7,
18 | "ask": 1928.3,
19 | "lastTraded": null
20 | },
21 | "lowPrice": {
22 | "bid": 1926.4,
23 | "ask": 1927.0,
24 | "lastTraded": null
25 | },
26 | "lastTradedVolume": 60
27 | },
28 | {
29 | "snapshotTime": "2020/10/12 21:51:00",
30 | "snapshotTimeUTC": "2020-10-12T20:51:00",
31 | "openPrice": {
32 | "bid": 1927.4,
33 | "ask": 1928.0,
34 | "lastTraded": null
35 | },
36 | "closePrice": {
37 | "bid": 1927.1,
38 | "ask": 1927.7,
39 | "lastTraded": null
40 | },
41 | "highPrice": {
42 | "bid": 1927.4,
43 | "ask": 1928.0,
44 | "lastTraded": null
45 | },
46 | "lowPrice": {
47 | "bid": 1926.7,
48 | "ask": 1927.3,
49 | "lastTraded": null
50 | },
51 | "lastTradedVolume": 31
52 | },
53 | {
54 | "snapshotTime": "2020/10/12 21:52:00",
55 | "snapshotTimeUTC": "2020-10-12T20:52:00",
56 | "openPrice": {
57 | "bid": 1927.2,
58 | "ask": 1927.8,
59 | "lastTraded": null
60 | },
61 | "closePrice": {
62 | "bid": 1927.0,
63 | "ask": 1927.6,
64 | "lastTraded": null
65 | },
66 | "highPrice": {
67 | "bid": 1927.2,
68 | "ask": 1927.8,
69 | "lastTraded": null
70 | },
71 | "lowPrice": {
72 | "bid": 1927.0,
73 | "ask": 1927.6,
74 | "lastTraded": null
75 | },
76 | "lastTradedVolume": 4
77 | },
78 | {
79 | "snapshotTime": "2020/10/12 21:53:00",
80 | "snapshotTimeUTC": "2020-10-12T20:53:00",
81 | "openPrice": {
82 | "bid": 1927.1,
83 | "ask": 1927.7,
84 | "lastTraded": null
85 | },
86 | "closePrice": {
87 | "bid": 1927.3,
88 | "ask": 1927.9,
89 | "lastTraded": null
90 | },
91 | "highPrice": {
92 | "bid": 1927.5,
93 | "ask": 1928.1,
94 | "lastTraded": null
95 | },
96 | "lowPrice": {
97 | "bid": 1927.1,
98 | "ask": 1927.7,
99 | "lastTraded": null
100 | },
101 | "lastTradedVolume": 6
102 | },
103 | {
104 | "snapshotTime": "2020/10/12 21:54:00",
105 | "snapshotTimeUTC": "2020-10-12T20:54:00",
106 | "openPrice": {
107 | "bid": 1927.4,
108 | "ask": 1928.0,
109 | "lastTraded": null
110 | },
111 | "closePrice": {
112 | "bid": 1927.2,
113 | "ask": 1927.8,
114 | "lastTraded": null
115 | },
116 | "highPrice": {
117 | "bid": 1927.4,
118 | "ask": 1928.0,
119 | "lastTraded": null
120 | },
121 | "lowPrice": {
122 | "bid": 1927.2,
123 | "ask": 1927.8,
124 | "lastTraded": null
125 | },
126 | "lastTradedVolume": 5
127 | },
128 | {
129 | "snapshotTime": "2020/10/12 21:55:00",
130 | "snapshotTimeUTC": "2020-10-12T20:55:00",
131 | "openPrice": {
132 | "bid": 1927.3,
133 | "ask": 1927.9,
134 | "lastTraded": null
135 | },
136 | "closePrice": {
137 | "bid": 1927.2,
138 | "ask": 1927.8,
139 | "lastTraded": null
140 | },
141 | "highPrice": {
142 | "bid": 1927.3,
143 | "ask": 1927.9,
144 | "lastTraded": null
145 | },
146 | "lowPrice": {
147 | "bid": 1927.1,
148 | "ask": 1927.7,
149 | "lastTraded": null
150 | },
151 | "lastTradedVolume": 26
152 | },
153 | {
154 | "snapshotTime": "2020/10/12 21:56:00",
155 | "snapshotTimeUTC": "2020-10-12T20:56:00",
156 | "openPrice": {
157 | "bid": 1927.0,
158 | "ask": 1927.6,
159 | "lastTraded": null
160 | },
161 | "closePrice": {
162 | "bid": 1927.0,
163 | "ask": 1927.6,
164 | "lastTraded": null
165 | },
166 | "highPrice": {
167 | "bid": 1927.1,
168 | "ask": 1927.7,
169 | "lastTraded": null
170 | },
171 | "lowPrice": {
172 | "bid": 1927.0,
173 | "ask": 1927.6,
174 | "lastTraded": null
175 | },
176 | "lastTradedVolume": 20
177 | },
178 | {
179 | "snapshotTime": "2020/10/12 21:57:00",
180 | "snapshotTimeUTC": "2020-10-12T20:57:00",
181 | "openPrice": {
182 | "bid": 1926.8,
183 | "ask": 1927.4,
184 | "lastTraded": null
185 | },
186 | "closePrice": {
187 | "bid": 1926.7,
188 | "ask": 1927.3,
189 | "lastTraded": null
190 | },
191 | "highPrice": {
192 | "bid": 1926.9,
193 | "ask": 1927.5,
194 | "lastTraded": null
195 | },
196 | "lowPrice": {
197 | "bid": 1926.7,
198 | "ask": 1927.3,
199 | "lastTraded": null
200 | },
201 | "lastTradedVolume": 49
202 | },
203 | {
204 | "snapshotTime": "2020/10/12 21:58:00",
205 | "snapshotTimeUTC": "2020-10-12T20:58:00",
206 | "openPrice": {
207 | "bid": 1926.8,
208 | "ask": 1927.4,
209 | "lastTraded": null
210 | },
211 | "closePrice": {
212 | "bid": 1927.0,
213 | "ask": 1927.6,
214 | "lastTraded": null
215 | },
216 | "highPrice": {
217 | "bid": 1927.0,
218 | "ask": 1927.6,
219 | "lastTraded": null
220 | },
221 | "lowPrice": {
222 | "bid": 1926.7,
223 | "ask": 1927.3,
224 | "lastTraded": null
225 | },
226 | "lastTradedVolume": 39
227 | },
228 | {
229 | "snapshotTime": "2020/10/12 21:59:00",
230 | "snapshotTimeUTC": "2020-10-12T20:59:00",
231 | "openPrice": {
232 | "bid": 1926.9,
233 | "ask": 1927.5,
234 | "lastTraded": null
235 | },
236 | "closePrice": {
237 | "bid": 1927.1,
238 | "ask": 1927.7,
239 | "lastTraded": null
240 | },
241 | "highPrice": {
242 | "bid": 1927.1,
243 | "ask": 1927.7,
244 | "lastTraded": null
245 | },
246 | "lowPrice": {
247 | "bid": 1926.9,
248 | "ask": 1927.5,
249 | "lastTraded": null
250 | },
251 | "lastTradedVolume": 24
252 | }
253 | ],
254 | "instrumentType": "COMMODITIES",
255 | "metadata": {
256 | "allowance": {
257 | "remainingAllowance": 9644,
258 | "totalAllowance": 10000,
259 | "allowanceExpiry": 69976
260 | },
261 | "size": 10,
262 | "pageData": {
263 | "pageSize": 20,
264 | "pageNumber": 1,
265 | "totalPages": 1
266 | }
267 | }
268 | }
--------------------------------------------------------------------------------
/tests/data/historic_prices_num_points.json:
--------------------------------------------------------------------------------
1 | {
2 | "prices": [
3 | {
4 | "snapshotTime": "2020/08/10 00:00:00",
5 | "snapshotTimeUTC": "2020-08-09T23:00:00",
6 | "openPrice": {
7 | "bid": 2028.0,
8 | "ask": 2028.0,
9 | "lastTraded": null
10 | },
11 | "closePrice": {
12 | "bid": 1953.7,
13 | "ask": 1953.7,
14 | "lastTraded": null
15 | },
16 | "highPrice": {
17 | "bid": 2060.5,
18 | "ask": 2061.1,
19 | "lastTraded": null
20 | },
21 | "lowPrice": {
22 | "bid": 1874.3,
23 | "ask": 1874.9,
24 | "lastTraded": null
25 | },
26 | "lastTradedVolume": 1196283
27 | },
28 | {
29 | "snapshotTime": "2020/08/17 00:00:00",
30 | "snapshotTimeUTC": "2020-08-16T23:00:00",
31 | "openPrice": {
32 | "bid": 1949.8,
33 | "ask": 1949.8,
34 | "lastTraded": null
35 | },
36 | "closePrice": {
37 | "bid": 1947.4,
38 | "ask": 1947.4,
39 | "lastTraded": null
40 | },
41 | "highPrice": {
42 | "bid": 2023.8,
43 | "ask": 2024.4,
44 | "lastTraded": null
45 | },
46 | "lowPrice": {
47 | "bid": 1916.4,
48 | "ask": 1917.0,
49 | "lastTraded": null
50 | },
51 | "lastTradedVolume": 1171405
52 | },
53 | {
54 | "snapshotTime": "2020/08/24 00:00:00",
55 | "snapshotTimeUTC": "2020-08-23T23:00:00",
56 | "openPrice": {
57 | "bid": 1947.0,
58 | "ask": 1947.0,
59 | "lastTraded": null
60 | },
61 | "closePrice": {
62 | "bid": 1972.6,
63 | "ask": 1972.6,
64 | "lastTraded": null
65 | },
66 | "highPrice": {
67 | "bid": 1986.6,
68 | "ask": 1987.2,
69 | "lastTraded": null
70 | },
71 | "lowPrice": {
72 | "bid": 1908.2,
73 | "ask": 1908.8,
74 | "lastTraded": null
75 | },
76 | "lastTradedVolume": 1128584
77 | },
78 | {
79 | "snapshotTime": "2020/08/31 00:00:00",
80 | "snapshotTimeUTC": "2020-08-30T23:00:00",
81 | "openPrice": {
82 | "bid": 1974.9,
83 | "ask": 1974.9,
84 | "lastTraded": null
85 | },
86 | "closePrice": {
87 | "bid": 1940.9,
88 | "ask": 1940.9,
89 | "lastTraded": null
90 | },
91 | "highPrice": {
92 | "bid": 2000.4,
93 | "ask": 2001.0,
94 | "lastTraded": null
95 | },
96 | "lowPrice": {
97 | "bid": 1921.7,
98 | "ask": 1922.3,
99 | "lastTraded": null
100 | },
101 | "lastTradedVolume": 1005035
102 | },
103 | {
104 | "snapshotTime": "2020/09/07 00:00:00",
105 | "snapshotTimeUTC": "2020-09-06T23:00:00",
106 | "openPrice": {
107 | "bid": 1934.3,
108 | "ask": 1934.3,
109 | "lastTraded": null
110 | },
111 | "closePrice": {
112 | "bid": 1948.1,
113 | "ask": 1948.1,
114 | "lastTraded": null
115 | },
116 | "highPrice": {
117 | "bid": 1974.8,
118 | "ask": 1975.4,
119 | "lastTraded": null
120 | },
121 | "lowPrice": {
122 | "bid": 1911.7,
123 | "ask": 1912.3,
124 | "lastTraded": null
125 | },
126 | "lastTradedVolume": 802470
127 | },
128 | {
129 | "snapshotTime": "2020/09/14 00:00:00",
130 | "snapshotTimeUTC": "2020-09-13T23:00:00",
131 | "openPrice": {
132 | "bid": 1947.9,
133 | "ask": 1947.9,
134 | "lastTraded": null
135 | },
136 | "closePrice": {
137 | "bid": 1957.1,
138 | "ask": 1957.1,
139 | "lastTraded": null
140 | },
141 | "highPrice": {
142 | "bid": 1983.0,
143 | "ask": 1983.6,
144 | "lastTraded": null
145 | },
146 | "lowPrice": {
147 | "bid": 1938.5,
148 | "ask": 1939.1,
149 | "lastTraded": null
150 | },
151 | "lastTradedVolume": 834497
152 | },
153 | {
154 | "snapshotTime": "2020/09/21 00:00:00",
155 | "snapshotTimeUTC": "2020-09-20T23:00:00",
156 | "openPrice": {
157 | "bid": 1962.1,
158 | "ask": 1962.1,
159 | "lastTraded": null
160 | },
161 | "closePrice": {
162 | "bid": 1864.3,
163 | "ask": 1864.3,
164 | "lastTraded": null
165 | },
166 | "highPrice": {
167 | "bid": 1962.6,
168 | "ask": 1963.2,
169 | "lastTraded": null
170 | },
171 | "lowPrice": {
172 | "bid": 1851.0,
173 | "ask": 1852.0,
174 | "lastTraded": null
175 | },
176 | "lastTradedVolume": 1116122
177 | },
178 | {
179 | "snapshotTime": "2020/09/28 00:00:00",
180 | "snapshotTimeUTC": "2020-09-27T23:00:00",
181 | "openPrice": {
182 | "bid": 1866.3,
183 | "ask": 1866.3,
184 | "lastTraded": null
185 | },
186 | "closePrice": {
187 | "bid": 1904.1,
188 | "ask": 1904.1,
189 | "lastTraded": null
190 | },
191 | "highPrice": {
192 | "bid": 1923.2,
193 | "ask": 1923.8,
194 | "lastTraded": null
195 | },
196 | "lowPrice": {
197 | "bid": 1851.4,
198 | "ask": 1852.0,
199 | "lastTraded": null
200 | },
201 | "lastTradedVolume": 856763
202 | },
203 | {
204 | "snapshotTime": "2020/10/05 00:00:00",
205 | "snapshotTimeUTC": "2020-10-04T23:00:00",
206 | "openPrice": {
207 | "bid": 1907.6,
208 | "ask": 1907.6,
209 | "lastTraded": null
210 | },
211 | "closePrice": {
212 | "bid": 1936.3,
213 | "ask": 1936.3,
214 | "lastTraded": null
215 | },
216 | "highPrice": {
217 | "bid": 1936.4,
218 | "ask": 1937.0,
219 | "lastTraded": null
220 | },
221 | "lowPrice": {
222 | "bid": 1876.9,
223 | "ask": 1877.5,
224 | "lastTraded": null
225 | },
226 | "lastTradedVolume": 728781
227 | },
228 | {
229 | "snapshotTime": "2020/10/12 00:00:00",
230 | "snapshotTimeUTC": "2020-10-11T23:00:00",
231 | "openPrice": {
232 | "bid": 1926.2,
233 | "ask": 1926.2,
234 | "lastTraded": null
235 | },
236 | "closePrice": {
237 | "bid": 1906.6,
238 | "ask": 1907.2,
239 | "lastTraded": null
240 | },
241 | "highPrice": {
242 | "bid": 1939.1,
243 | "ask": 1939.7,
244 | "lastTraded": null
245 | },
246 | "lowPrice": {
247 | "bid": 1884.8,
248 | "ask": 1885.4,
249 | "lastTraded": null
250 | },
251 | "lastTradedVolume": 364914
252 | }
253 | ],
254 | "instrumentType": "COMMODITIES",
255 | "metadata": {
256 | "allowance": {
257 | "remainingAllowance": 9952,
258 | "totalAllowance": 10000,
259 | "allowanceExpiry": 565788
260 | },
261 | "size": 10,
262 | "pageData": {
263 | "pageSize": 20,
264 | "pageNumber": 1,
265 | "totalPages": 1
266 | }
267 | }
268 | }
--------------------------------------------------------------------------------
/predefined_functions/algo_catch_trends_from_different_markets.py:
--------------------------------------------------------------------------------
1 | from trading_ig.config import config
2 | import logging
3 |
4 | logger = logging.getLogger(__name__)
5 | logger.setLevel(logging.DEBUG)
6 |
7 | # if you need to cache to DB your requests
8 | from datetime import timedelta
9 | import requests_cache
10 | from getting_realtime_data.data_retrieval import Data_Retrieval
11 | from sending_orders.order_management import Order_Management
12 | from management_of_position.position_management import Position_Management
13 | from predefined_functions.initialisation import Initialisation
14 | from get_data.get_market_data import Get_Market_Data
15 | import time
16 | from datetime import datetime, timedelta
17 | from predefined_functions.defined_functionality import Defined_Functionality
18 | import pandas
19 | import traceback
20 |
21 |
22 | # the newest one where you make market order base on price movements 5 or more and try to catch the trend
23 |
24 | class Algo0:
25 | def __init__(self):
26 | logging.basicConfig(level=logging.INFO)
27 | self.df = Defined_Functionality()
28 |
29 |
30 |
31 | # list_of_epics = ['IX.D.DOW.DAILY.IP']
32 | # list_of_epics = ['IX.D.SPTRD.DAILY.IP']
33 | # list_of_epics = ['CS.D.EURUSD.TODAY.IP']
34 | list_of_epics = [
35 | 'IX.D.DOW.DAILY.IP',
36 | 'IX.D.SPTRD.DAILY.IP',
37 | 'IX.D.FTSE.DAILY.IP'
38 | ]
39 |
40 | self.df.set_epics_to_look_for(epic_list=list_of_epics)
41 |
42 | self.tradeable_epic = ['IX.D.DOW.DAILY.IP']
43 |
44 | self.map_epic_data_minute = {}
45 | for epic in list_of_epics:
46 | self.map_epic_data_minute[epic] = []
47 |
48 | self.first_timestamp = None
49 | self.high = None
50 | self.low = None
51 |
52 | def setup(self):
53 | self.df.initialise_connection()
54 | # not required as we are not trailing any losses
55 | # time.sleep(2)
56 | # self.df.get_market_data()
57 | # self.df.update_stop_level_bands()
58 |
59 | def run(self):
60 |
61 | while (True):
62 | try:
63 | self.setup()
64 |
65 | for epic in self.tradeable_epic:
66 |
67 | signals_and_levels = self.signal_generation(epic_list=self.map_epic_data_minute.keys())
68 | position = self.create_position(signal=signals_and_levels, epic=epic)
69 | if position == "error": continue
70 | self.closing_incrments(position=position,signals=signals_and_levels)
71 |
72 | except Exception as e:
73 | print(e, " error in the looping for the defined_functionality")
74 |
75 | traceback.print_exc()
76 |
77 |
78 |
79 |
80 | def create_position(self, signal, epic):
81 | position = self.df.find_open_position_by_epic(epic=epic)
82 |
83 | if position == "error": return position
84 | if len(position) >= 1: return position
85 | if signal == None: return None
86 |
87 | key=None
88 | if signal["BUY"]:
89 | key = "BUY"
90 | elif signal["SELL"]:
91 | key = "SELL"
92 |
93 | if key == None: return None
94 |
95 | position = self.df.create_open_position(epic=epic, direction=key, size=0.5)
96 | return position
97 |
98 |
99 | def closing_incrments(self, position, signals):
100 | position = position[0]
101 | direction = position["position"]["direction"]
102 | epic = position["market"]["epic"]
103 | opening_price = position["position"]["openLevel"]
104 |
105 | data = self.df.get_market_data(epic=epic)
106 | bid = data["snapshot"]["bid"]
107 | offer = data["snapshot"]["offer"]
108 |
109 | spread = offer - bid
110 |
111 | boolean_close_buy = False
112 | boolean_close_sell = False
113 |
114 | if direction == "BUY":
115 | boolean_close_buy = opening_price < (bid - spread)
116 |
117 | elif direction == "SELL":
118 | boolean_close_sell = opening_price > (offer + spread)
119 |
120 | if boolean_close_buy or boolean_close_sell:
121 | closing_increment = self.df.close_position(size=0.01,position=position)
122 | return closing_increment
123 | return None
124 |
125 |
126 |
127 | def signal_generation(self, epic_list):
128 | signals_levels = None
129 | # minute_10 = 60 * 10
130 | # minute_10 = 60
131 | minute_10 = 6
132 | datetime_now = datetime.now()
133 | limit = 3
134 | data = None
135 |
136 | signal_matrix = {}
137 |
138 | capture_time = False
139 |
140 | for epic in epic_list:
141 |
142 | if (self.first_timestamp != None):
143 | difference = (datetime_now - self.first_timestamp)
144 | # appending data into df map_epic_data
145 | data = self.df.get_market_data(epic=epic)
146 | # self.finding_lows_highs(data=data)
147 |
148 | if (difference.seconds > minute_10):
149 | capture_time = True
150 | data = self.df.get_market_data(epic=epic)
151 | self.map_epic_data_minute[epic].append(data)
152 | # self.finding_lows_highs(data=data, reset=True)
153 |
154 | else:
155 | data = self.df.get_market_data(epic=epic)
156 | capture_time = True
157 | self.map_epic_data_minute[epic].append(data)
158 | # self.finding_lows_highs(data=data)
159 |
160 | if len(self.map_epic_data_minute[epic]) > limit:
161 | self.map_epic_data_minute[epic].pop(0)
162 |
163 | sell_level = None
164 | buy_level = None
165 |
166 | object_epic_data = self.map_epic_data_minute[epic][-1]
167 | bid = object_epic_data["snapshot"]["bid"]
168 | offer = object_epic_data["snapshot"]["offer"]
169 | high = object_epic_data["snapshot"]["high"]
170 | low = object_epic_data["snapshot"]["low"]
171 |
172 | object_epic_data = self.map_epic_data_minute[epic][-2]
173 | bid_second = object_epic_data["snapshot"]["bid"]
174 | offer_second = object_epic_data["snapshot"]["offer"]
175 | high_second = object_epic_data["snapshot"]["high"]
176 | low_second = object_epic_data["snapshot"]["low"]
177 |
178 | object_epic_data = self.map_epic_data_minute[epic][-3]
179 | bid_third = object_epic_data["snapshot"]["bid"]
180 | offer_third = object_epic_data["snapshot"]["offer"]
181 | high_third = object_epic_data["snapshot"]["high"]
182 | low_third = object_epic_data["snapshot"]["low"]
183 | # the price is going down there you should buy
184 | if offer_third > offer_second > offer:
185 | buy_level = 1
186 | # the price is going up therefore you should sell
187 | elif bid_third < bid_second < bid:
188 | sell_level = 1
189 |
190 | signal_matrix[epic] = {
191 | "SELL": sell_level,
192 | "BUY": buy_level
193 | }
194 |
195 | if capture_time:
196 | self.first_timestamp = datetime_now
197 |
198 | key = list(self.map_epic_data_minute.keys())[0]
199 | # because up above you remove one item from the list
200 |
201 | if (not key in signal_matrix) or (len(signal_matrix) == 0):
202 | return None
203 |
204 | sell_level = signal_matrix[key]["SELL"]
205 | buy_level = signal_matrix[key]["BUY"]
206 | for epic in signal_matrix.keys():
207 | sell_level = sell_level and signal_matrix[epic]["SELL"]
208 | buy_level = buy_level and signal_matrix[epic]["BUY"]
209 |
210 | # once you have a signal_matrix made you need to find if a signal exists
211 | signals_levels = {
212 | "SELL": sell_level,
213 | "BUY": buy_level
214 | }
215 | return signals_levels
216 |
217 | def finding_lows_highs(self, data, reset=False):
218 |
219 | bid = data["snapshot"]["bid"]
220 | offer = data["snapshot"]["offer"]
221 |
222 | if reset:
223 | epic = data["instrument"]["epic"]
224 | object_dict = self.map_epic_data_minute[epic][-1]
225 | object_dict["snapshot"]["high"] = self.high
226 | object_dict["snapshot"]["low"] = self.low
227 | self.map_epic_data_minute[epic][-1] = object_dict
228 | # start looking at the new interval
229 | if self.high == None or reset:
230 | self.high = offer
231 | if self.low == None or reset:
232 | self.low = bid
233 |
234 | if bid < self.low:
235 | self.low = bid
236 | if offer > self.high:
237 | self.high = offer
238 |
239 |
240 |
241 |
242 |
243 |
244 |
--------------------------------------------------------------------------------