File size: 114,253 Bytes
5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 5d5dd44 5e78fe5 d0f2aec 5e78fe5 a39f235 5e78fe5 d0f2aec 5e78fe5 5d5dd44 d0f2aec 5d5dd44 5e78fe5 5d5dd44 5e78fe5 5d5dd44 5e78fe5 d0f2aec 5e78fe5 5d5dd44 5e78fe5 ab0f626 5e78fe5 5d5dd44 5e78fe5 5d5dd44 5e78fe5 ab0f626 5e78fe5 5d5dd44 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 5d5dd44 5e78fe5 5d5dd44 5e78fe5 5d5dd44 5e78fe5 d0f2aec 5e78fe5 5d5dd44 5e78fe5 5d5dd44 5e78fe5 5d5dd44 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 5d5dd44 5e78fe5 5d5dd44 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 5d5dd44 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 5d5dd44 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5d5dd44 5e78fe5 d0f2aec 5e78fe5 d0f2aec 5e78fe5 5d5dd44 d0f2aec 5d5dd44 d0f2aec 5d5dd44 d0f2aec 5d5dd44 5e78fe5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 |
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "nwaAZRu1NTiI"
},
"source": [
"# Q-learning \n",
"\n",
"#### This version implements q-learning using a custom enviroment \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "DDf1gLC2NTiK"
},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mFailed to start the Kernel. \n",
"Cannot execute code, session has been disposed. \n",
"View Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details."
]
}
],
"source": [
"# !pip install -r ./requirements.txt\n",
"# !pip install stable_baselines3[extra]\n",
"# !pip install yfinance\n",
"# !pip install talib-binary\n",
"# !pip install huggingface_sb3\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "LNXxxKojNTiL"
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"import gym\n",
"from gym import spaces\n",
"from gym.utils import seeding\n",
"\n",
"import talib as ta\n",
"from tqdm.notebook import tqdm\n",
"\n",
"import yfinance as yf\n",
"import pandas as pd\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "dmAuEhZZNTiL"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3024\n",
"1875\n"
]
}
],
"source": [
"# Get data\n",
"eth_usd = yf.Ticker(\"ETH-USD\")\n",
"eth = eth_usd.history(period=\"max\")\n",
"\n",
"btc_usd = yf.Ticker(\"BTC-USD\")\n",
"btc = btc_usd.history(period=\"max\")\n",
"print(len(btc))\n",
"print(len(eth))\n",
"\n",
"btc_train = eth[-3015:-200]\n",
"# btc_test = eth[-200:]\n",
"eth_train = eth[-1864:-200]\n",
"eth_test = eth[-200:]\n",
"# len(eth_train)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def initialize_q_table(state_space, action_space):\n",
" Qtable = np.zeros((state_space, action_space))\n",
" return Qtable"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# Policy\n",
"\n",
"def greedy_policy(Qtable, state):\n",
" # Exploitation: take the action with the highest state, action value\n",
" # if we dont have a state with values return DO_NOTHING \n",
" if abs(np.max(Qtable[state])) > 0:\n",
" action = np.argmax(Qtable[state])\n",
" else:\n",
" action = 2\n",
" # action = np.argmax(Qtable[state])\n",
" return action\n",
"\n",
"\n",
"def epsilon_greedy_policy(Qtable, state, epsilon, env):\n",
" # Randomly generate a number between 0 and 1\n",
" random_num = np.random.uniform(size=1)\n",
" # if random_num > greater than epsilon --> exploitation\n",
" if random_num > epsilon:\n",
" # Take the action with the highest value given a state\n",
" # np.argmax can be useful here\n",
" action = greedy_policy(Qtable, state)\n",
" # else --> exploration\n",
" else:\n",
" # action = np.random.random_integers(4,size=1)[0]\n",
" action = env.action_space.sample()\n",
" \n",
" return action"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"id": "wlC-EdLENTiN"
},
"outputs": [],
"source": [
"def train(n_training_episodes, min_epsilon, max_epsilon, decay_rate, env, max_steps, Qtable, learning_rate, gamma):\n",
" state_history = []\n",
" \n",
" for episode in range(n_training_episodes):\n",
" # Reduce epsilon (because we need less and less exploration)\n",
" epsilon = min_epsilon + (max_epsilon - min_epsilon)*np.exp(-decay_rate*episode)\n",
" # Reset the environment\n",
" state = env.reset()\n",
" step = 0\n",
" done = False\n",
"\n",
" # repeat\n",
" for step in range(max_steps):\n",
" # Choose the action At using epsilon greedy policy\n",
" action = epsilon_greedy_policy(Qtable, state, epsilon, env)\n",
"\n",
" # Take action At and observe Rt+1 and St+1\n",
" # Take the action (a) and observe the outcome state(s') and reward (r)\n",
" new_state, reward, done, info = env.step(action)\n",
"\n",
" # Update Q(s,a):= Q(s,a) + lr [R(s,a) + gamma * max Q(s',a') - Q(s,a)]\n",
" Qtable[state][action] = Qtable[state][action] + learning_rate * (reward + gamma * ( np.max(Qtable[new_state]) ) - Qtable[state][action] )\n",
"\n",
" # If done, finish the episode\n",
" if done:\n",
" break\n",
" \n",
" # Our next state is the new state\n",
" state = new_state\n",
"\n",
" state_history.append(state) \n",
"\n",
" return Qtable, state_history"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"from enum import Enum\n",
"class Actions(Enum):\n",
" Sell = 0\n",
" Buy = 1\n",
" Do_nothing = 2\n",
"\n",
"class CustTradingEnv(gym.Env):\n",
"\n",
" def __init__(self, df, max_steps=0, random_start=True):\n",
" self.seed()\n",
" self.df = df\n",
" self.prices, self.signal_features = self._process_data()\n",
"\n",
" # spaces\n",
" self.action_space = spaces.Discrete(3)\n",
" self.observation_space = spaces.Box(low=0, high=1999, shape=(1,) , dtype=np.float64)\n",
"\n",
" # episode\n",
" self._start_tick = 0\n",
" self._end_tick = 0\n",
" self._done = None\n",
" self._current_tick = None\n",
" self._last_trade_tick = None\n",
" self._position = None\n",
" self._position_history = None\n",
" self._total_reward = None\n",
" self._total_profit = None\n",
" self._first_rendering = None\n",
" self.history = None\n",
" self._max_steps = max_steps\n",
" self._start_episode_tick = None\n",
" self._trade_history = None\n",
" self._random_start = random_start\n",
"\n",
" def reset(self):\n",
" self._done = False\n",
" if self._random_start:\n",
" self._start_episode_tick = np.random.randint(1,high=len(self.df)- self._max_steps )\n",
" self._end_tick = self._start_episode_tick + self._max_steps\n",
" else:\n",
" self._start_episode_tick = 1\n",
" self._end_tick = len(self.df)-1\n",
" # self._start_episode_tick = np.random.randint(1,len(self.df)- self._max_steps )\n",
" # self._end_tick = self._start_episode_tick + self._max_steps\n",
" self._current_tick = self._start_episode_tick\n",
" self._last_trade_tick = self._current_tick - 1\n",
" self._position = 0\n",
" self._position_history = []\n",
" # self._position_history = (self.window_size * [None]) + [self._position]\n",
" self._total_reward = 0.\n",
" self._total_profit = 0.\n",
" self._trade_history = []\n",
" self.history = {}\n",
" return self._get_observation()\n",
"\n",
"\n",
" def step(self, action):\n",
" self._done = False\n",
" self._current_tick += 1\n",
"\n",
" if self._current_tick == self._end_tick:\n",
" self._done = True\n",
"\n",
" step_reward = self._calculate_reward(action)\n",
" self._total_reward += step_reward\n",
"\n",
" observation = self._get_observation()\n",
" info = dict(\n",
" total_reward = self._total_reward,\n",
" total_profit = self._total_profit,\n",
" position = self._position,\n",
" action = action\n",
" )\n",
" self._update_history(info)\n",
"\n",
" return observation, step_reward, self._done, info\n",
"\n",
" def seed(self, seed=None):\n",
" self.np_random, seed = seeding.np_random(seed)\n",
" return [seed]\n",
" \n",
" def _get_observation(self):\n",
" return self.signal_features[self._current_tick]\n",
"\n",
" def _update_history(self, info):\n",
" if not self.history:\n",
" self.history = {key: [] for key in info.keys()}\n",
"\n",
" for key, value in info.items():\n",
" self.history[key].append(value)\n",
"\n",
"\n",
" def render(self, mode='human'):\n",
" window_ticks = np.arange(len(self._position_history))\n",
" prices = self.prices[self._start_episode_tick:self._end_tick+1]\n",
" plt.plot(prices)\n",
"\n",
" open_buy = []\n",
" close_buy = []\n",
" open_sell = []\n",
" close_sell = []\n",
" do_nothing = []\n",
"\n",
" for i, tick in enumerate(window_ticks):\n",
" if self._position_history[i] == 1:\n",
" open_buy.append(tick)\n",
" elif self._position_history[i] == 2 :\n",
" close_buy.append(tick)\n",
" elif self._position_history[i] == 3 :\n",
" open_sell.append(tick)\n",
" elif self._position_history[i] == 4 :\n",
" close_sell.append(tick)\n",
" elif self._position_history[i] == 0 :\n",
" do_nothing.append(tick)\n",
"\n",
" plt.plot(open_buy, prices[open_buy], 'go', marker=\"^\")\n",
" plt.plot(close_buy, prices[close_buy], 'go', marker=\"v\")\n",
" plt.plot(open_sell, prices[open_sell], 'ro', marker=\"v\")\n",
" plt.plot(close_sell, prices[close_sell], 'ro', marker=\"^\")\n",
" \n",
" plt.plot(do_nothing, prices[do_nothing], 'yo')\n",
"\n",
" plt.suptitle(\n",
" \"Total Reward: %.6f\" % self._total_reward + ' ~ ' +\n",
" \"Total Profit: %.6f\" % self._total_profit\n",
" )\n",
"\n",
" def _calculate_reward(self, action):\n",
" step_reward = 0\n",
"\n",
" current_price = self.prices[self._current_tick]\n",
" last_price = self.prices[self._current_tick - 1]\n",
" price_diff = current_price - last_price\n",
"\n",
" penalty = -1 * last_price * 0.01\n",
" # OPEN BUY - 1\n",
" if action == Actions.Buy.value and self._position == 0:\n",
" self._position = 1\n",
" step_reward += price_diff\n",
" self._last_trade_tick = self._current_tick - 1\n",
" self._position_history.append(1)\n",
"\n",
" elif action == Actions.Buy.value and self._position > 0:\n",
" step_reward += penalty\n",
" self._position_history.append(-1)\n",
" # CLOSE SELL - 4\n",
" elif action == Actions.Buy.value and self._position < 0:\n",
" self._position = 0\n",
" step_reward += -1 * (self.prices[self._current_tick -1] - self.prices[self._last_trade_tick]) \n",
" self._total_profit += step_reward\n",
" self._position_history.append(4)\n",
" self._trade_history.append(step_reward)\n",
"\n",
" # OPEN SELL - 3\n",
" elif action == Actions.Sell.value and self._position == 0:\n",
" self._position = -1\n",
" step_reward += -1 * price_diff\n",
" self._last_trade_tick = self._current_tick - 1\n",
" self._position_history.append(3)\n",
" # CLOSE BUY - 2\n",
" elif action == Actions.Sell.value and self._position > 0:\n",
" self._position = 0\n",
" step_reward += self.prices[self._current_tick -1] - self.prices[self._last_trade_tick] \n",
" self._total_profit += step_reward\n",
" self._position_history.append(2)\n",
" self._trade_history.append(step_reward)\n",
" elif action == Actions.Sell.value and self._position < 0:\n",
" step_reward += penalty\n",
" self._position_history.append(-1)\n",
"\n",
" # DO NOTHING - 0\n",
" elif action == Actions.Do_nothing.value and self._position > 0:\n",
" step_reward += price_diff\n",
" self._position_history.append(0)\n",
" elif action == Actions.Do_nothing.value and self._position < 0:\n",
" step_reward += -1 * price_diff\n",
" self._position_history.append(0)\n",
" elif action == Actions.Do_nothing.value and self._position == 0:\n",
" step_reward += -1 * abs(price_diff)\n",
" self._position_history.append(0)\n",
"\n",
" return step_reward\n",
"\n",
" def _do_bin(self,df):\n",
" df = pd.cut(df,bins=[0,10,20,30,40,50,60,70,80,90,100],labels=False, include_lowest=True)\n",
" return df\n",
" # Our state will be encode with 4 features MFI and Stochastic(only D line), ADX and DI+DI-\n",
" # the values of each feature will be binned in 10 bins, ex:\n",
" # MFI goes from 0-100, if we get 25 will put on the second bin \n",
" # DI+DI- if DI+ is over DI- set (1 otherwise 0) \n",
" # \n",
" # that will give a state space of 10(MFI) * 10(STOCH) * 10(ADX) * 2(DI) = 2000 states\n",
" # encoded as bins of DI MFI STOCH ADX = 1 45.2 25.4 90.1 , binned = 1 4 2 9 state = 1429 \n",
" def _process_data(self):\n",
" timeperiod = 14\n",
" self.df = self.df.copy()\n",
" \n",
" self.df['mfi_r'] = ta.MFI(self.df['High'], self.df['Low'], self.df['Close'],self.df['Volume'], timeperiod=timeperiod)\n",
" _, self.df['stock_d_r'] = ta.STOCH(self.df['High'], self.df['Low'], self.df['Close'], fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)\n",
" self.df['adx_r'] = ta.ADX(self.df['High'], self.df['Low'], self.df['Close'], timeperiod=timeperiod)\n",
" self.df['p_di'] = ta.PLUS_DI(self.df['High'], self.df['Low'], self.df['Close'], timeperiod=timeperiod)\n",
" self.df['m_di'] = ta.MINUS_DI(self.df['High'], self.df['Low'], self.df['Close'], timeperiod=timeperiod)\n",
" self.df['di'] = np.where( self.df['p_di'] > self.df['m_di'], 1, 0)\n",
"\n",
" self.df = self.df.dropna()\n",
" self.df['mfi'] = self._do_bin(self.df['mfi_r'])\n",
" self.df['stock_d'] = self._do_bin(self.df['stock_d_r'])\n",
" self.df['adx'] = self._do_bin(self.df['adx_r'])\n",
" self.df['state'] = self.df['di']*1000+ self.df['mfi']*100 + self.df['stock_d']*10 + self.df['adx']\n",
"\n",
" prices = self.df.loc[:, 'Close'].to_numpy()\n",
" # print(self.df.head(30))\n",
"\n",
" signal_features = self.df.loc[:, 'state'].to_numpy()\n",
"\n",
" return prices, signal_features"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# Training parameters\n",
"n_training_episodes = 20000 # Total training episodes\n",
"learning_rate = 0.2 # Learning rate\n",
"\n",
"# Environment parameters\n",
"max_steps = 20 # Max steps per episode\n",
"gamma = 0.95 # Discounting rate\n",
"\n",
"# Exploration parameters\n",
"max_epsilon = 1.0 # Exploration probability at start\n",
"# max_epsilon = 1.0 # Exploration probability at start\n",
"min_epsilon = 0.05 # Minimum exploration probability \n",
"# min_epsilon = 0.05 # Minimum exploration probability \n",
"decay_rate = 0.0005 # Exponential decay rate for exploration prob"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "REhmfLkYNTiN",
"outputId": "cf676f6d-83df-43f5-89fe-3258e0041d9d"
},
"outputs": [],
"source": [
"# create env\n",
"env = CustTradingEnv(df=eth_train, max_steps=max_steps)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"# create q-table\n",
"\n",
"action_space = env.action_space.n # buy sell do_nothing\n",
"state_space = 2000\n",
"\n",
"Qtable_trading = initialize_q_table(state_space, action_space)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"981"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# train with ETH\n",
"Qtable_trading, state_history = train(n_training_episodes, min_epsilon, max_epsilon, \n",
" decay_rate, env, max_steps, Qtable_trading, learning_rate, gamma )\n",
"len(np.where( Qtable_trading > 0 )[0])\n",
"\n",
"# #train with BTC\n",
"# env = CustTradingEnv(df=btc_train, max_steps=max_steps)\n",
"# Qtable_trading, state_history = train(n_training_episodes, min_epsilon, max_epsilon, \n",
"# decay_rate, env, max_steps, Qtable_trading, learning_rate, gamma )\n",
"# len(np.where( Qtable_trading > 0 )[0])"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 417
},
"id": "FIQ0OqtsO3jo",
"outputId": "f98374ad-c7de-4dc4-80b1-25f018ad96eb"
},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 1080x432 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=(15,6))\n",
"plt.cla()\n",
"env.render()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[-168.9210205078125, 187.22998046875, 218.34100341796875]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"env._trade_history"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"351"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(np.unique(state_history, return_counts=True)[1])\n",
"# count = 0\n",
"# for i in range(len(state_history)):\n",
"# if state_history[i] == 1987:\n",
"# count +=1\n",
"# count"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"def evaluate_agent(env, max_steps, n_eval_episodes, Q, random=False):\n",
" \"\"\"\n",
" Evaluate the agent for ``n_eval_episodes`` episodes and returns average reward and std of reward.\n",
" :param env: The evaluation environment\n",
" :param n_eval_episodes: Number of episode to evaluate the agent\n",
" :param Q: The Q-table\n",
" :param seed: The evaluation seed array (for taxi-v3)\n",
" \"\"\"\n",
" episode_rewards = []\n",
" episode_profits = []\n",
" for episode in tqdm(range(n_eval_episodes), disable=random):\n",
" state = env.reset()\n",
" step = 0\n",
" done = False\n",
" total_rewards_ep = 0\n",
" total_profit_ep = 0\n",
" \n",
" for step in range(max_steps):\n",
" # Take the action (index) that have the maximum expected future reward given that state\n",
" if random:\n",
" action = env.action_space.sample()\n",
" else:\n",
" action = greedy_policy(Q, state)\n",
"\n",
" new_state, reward, done, info = env.step(action)\n",
" total_rewards_ep += reward\n",
" \n",
" if done:\n",
" break\n",
" state = new_state\n",
"\n",
" episode_rewards.append(total_rewards_ep)\n",
" episode_profits.append(env.history['total_profit'][-1])\n",
" # print(env.history)\n",
" # env.render()\n",
" # assert 0\n",
"\n",
" mean_reward = np.mean(episode_rewards)\n",
" std_reward = np.std(episode_rewards)\n",
" mean_profit = np.mean(episode_profits)\n",
" std_profit = np.std(episode_profits)\n",
"\n",
" return mean_reward, std_reward, mean_profit, std_profit"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "629507e6932b49d381644ae851b9f08e",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
" 0%| | 0/1000 [00:00<?, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"(-25.214183127441423,\n",
" 305.1328994776763,\n",
" 113.14856896972657,\n",
" 195.77032459962064)"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"max_steps = 20 \n",
"env_test = CustTradingEnv(df=eth_test, max_steps=max_steps, random_start=True)\n",
"n_eval_episodes = 1000\n",
"\n",
"evaluate_agent(env_test, max_steps, n_eval_episodes, Qtable_trading)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 1080x432 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=(15,6))\n",
"plt.cla()\n",
"env_test.render()"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "65be242101434cab9057cda9dd230391",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
" 0%| | 0/1 [00:00<?, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"(-654.2524291992195, 0.0, 563.6707763671875, 0.0)"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# trade sequential\n",
"max_steps = len(eth_test)\n",
"env_test = CustTradingEnv(df=eth_test, max_steps=max_steps, random_start=False)\n",
"n_eval_episodes = 1\n",
"\n",
"evaluate_agent(env_test, max_steps, n_eval_episodes, Qtable_trading)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(-196.17019008178713, 392.3658082003918, -18.1048154296875, 210.9968436183694)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Test for random n_eval_episodes\n",
"max_steps = 20 \n",
"env_test_rand = CustTradingEnv(df=eth_test, max_steps=max_steps, random_start=True)\n",
"n_eval_episodes = 1000\n",
"\n",
"evaluate_agent(env_test_rand, max_steps, n_eval_episodes, Qtable_trading, random=True)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Mean profit 39.304194213867184\n"
]
}
],
"source": [
"# trade sequentially with random actions \n",
"max_steps = len(eth_test)\n",
"env_test = CustTradingEnv(df=eth_test, max_steps=max_steps, random_start=False)\n",
"n_eval_episodes = 1\n",
"\n",
"all_profit=[]\n",
"for i in range(1000):\n",
" _,_,profit,_=evaluate_agent(env_test, max_steps, n_eval_episodes, Qtable_trading, random=True)\n",
" all_profit.append(profit)\n",
"print(f\"Mean profit {np.mean(all_profit)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## This is the result\n",
"\n",
"| Model | 1000 trades 20 steps | Sequential trading | 1000 trades 20 steps random actions | Sequential random|\n",
"|------------|----------------------|--------------------|-------------------------------------|------------------|\n",
"|Q-learning | 109.01 | 563.67 | -18.10 | 39.30 |\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def count_equal(env, Qtable):\n",
" count=0\n",
" for i in env.signal_features:\n",
" if abs(np.max(Qtable[i])) > 0:\n",
" count+=1\n",
" # else:\n",
" # print(i)\n",
" # assert 0\n",
" \n",
" print(len(env.signal_features), count, count / len(env.signal_features))\n",
"\n",
"count_equal(env_test, Qtable_trading)"
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3.8.13 ('rl2')",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "cd60ab8388a66026f336166410d6a8a46ddf65ece2e85ad2d46c8b98d87580d1"
}
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"01a2dbcb714e40148b41c761fcf43147": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "1.2.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "1.2.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"overflow_x": null,
"overflow_y": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"20b0f38ec3234ff28a62a286cd57b933": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "PasswordModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "PasswordModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "1.5.0",
"_view_name": "PasswordView",
"continuous_update": true,
"description": "Token:",
"description_tooltip": null,
"disabled": false,
"layout": "IPY_MODEL_01a2dbcb714e40148b41c761fcf43147",
"placeholder": "",
"style": "IPY_MODEL_90c874e91b304ee1a7ef147767ac00ce",
"value": ""
}
},
"270cbb5d6e9c4b1e9e2f39c8b3b0c15f": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "VBoxModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "VBoxModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "1.5.0",
"_view_name": "VBoxView",
"box_style": "",
"children": [
"IPY_MODEL_a02224a43d8d4af3bd31d326540d25da",
"IPY_MODEL_20b0f38ec3234ff28a62a286cd57b933",
"IPY_MODEL_f6c845330d6743c0b35c2c7ad834de77",
"IPY_MODEL_f1675c09d16a4251b403f9c56255f168",
"IPY_MODEL_c1a82965ae26479a98e4fdbde1e64ec2"
],
"layout": "IPY_MODEL_3fa248114ac24656ba74923936a94d2d"
}
},
"2dc5fa9aa3334dfcbdee9c238f2ef60b": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "DescriptionStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "DescriptionStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "StyleView",
"description_width": ""
}
},
"3e753b0212644990b558c68853ff2041": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "1.2.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "1.2.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"overflow_x": null,
"overflow_y": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"3fa248114ac24656ba74923936a94d2d": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "1.2.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "1.2.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": "center",
"align_self": null,
"border": null,
"bottom": null,
"display": "flex",
"flex": null,
"flex_flow": "column",
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"overflow_x": null,
"overflow_y": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": "50%"
}
},
"42d140b838b844819bc127afc1b7bc84": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "DescriptionStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "DescriptionStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "StyleView",
"description_width": ""
}
},
"90c874e91b304ee1a7ef147767ac00ce": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "DescriptionStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "DescriptionStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "StyleView",
"description_width": ""
}
},
"9d847f9a7d47458d8cd57d9b599e47c6": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "1.2.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "1.2.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"overflow_x": null,
"overflow_y": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"a02224a43d8d4af3bd31d326540d25da": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "1.5.0",
"_view_name": "HTMLView",
"description": "",
"description_tooltip": null,
"layout": "IPY_MODEL_caef095934ec47bbb8b64eab22049284",
"placeholder": "",
"style": "IPY_MODEL_2dc5fa9aa3334dfcbdee9c238f2ef60b",
"value": "<center> <img\nsrc=https://huggingface.co/front/assets/huggingface_logo-noborder.svg\nalt='Hugging Face'> <br> Copy a token from <a\nhref=\"https://huggingface.co/settings/tokens\" target=\"_blank\">your Hugging Face\ntokens page</a> and paste it below. <br> Immediately click login after copying\nyour token or it might be stored in plain text in this notebook file. </center>"
}
},
"a2cfb91cf66447d7899292854bd64a07": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "1.2.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "1.2.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"overflow_x": null,
"overflow_y": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"c1a82965ae26479a98e4fdbde1e64ec2": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "1.5.0",
"_view_name": "HTMLView",
"description": "",
"description_tooltip": null,
"layout": "IPY_MODEL_9d847f9a7d47458d8cd57d9b599e47c6",
"placeholder": "",
"style": "IPY_MODEL_42d140b838b844819bc127afc1b7bc84",
"value": "\n<b>Pro Tip:</b> If you don't already have one, you can create a dedicated\n'notebooks' token with 'write' access, that you can then easily reuse for all\nnotebooks. </center>"
}
},
"caef095934ec47bbb8b64eab22049284": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "1.2.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "1.2.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"overflow_x": null,
"overflow_y": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"eaba3f1de4444aabadfea2a3dadb1d80": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "DescriptionStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "DescriptionStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "StyleView",
"description_width": ""
}
},
"ee4a21bedc504171ad09d205d634b528": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "ButtonStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "ButtonStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "1.2.0",
"_view_name": "StyleView",
"button_color": null,
"font_weight": ""
}
},
"f1675c09d16a4251b403f9c56255f168": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "ButtonModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "ButtonModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "1.5.0",
"_view_name": "ButtonView",
"button_style": "",
"description": "Login",
"disabled": false,
"icon": "",
"layout": "IPY_MODEL_a2cfb91cf66447d7899292854bd64a07",
"style": "IPY_MODEL_ee4a21bedc504171ad09d205d634b528",
"tooltip": ""
}
},
"f6c845330d6743c0b35c2c7ad834de77": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "1.5.0",
"model_name": "CheckboxModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_model_name": "CheckboxModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "1.5.0",
"_view_name": "CheckboxView",
"description": "Add token as git credential?",
"description_tooltip": null,
"disabled": false,
"indent": true,
"layout": "IPY_MODEL_3e753b0212644990b558c68853ff2041",
"style": "IPY_MODEL_eaba3f1de4444aabadfea2a3dadb1d80",
"value": true
}
}
}
}
},
"nbformat": 4,
"nbformat_minor": 0
}
|