├── .gitignore ├── .nojekyll ├── 404.html ├── Dockerfile ├── LICENSE ├── LICENSE_ETC ├── NAV.md ├── README.md ├── SUMMARY.md ├── asset ├── LXGWWenKaiScreen.ttf ├── back-to-top.css ├── back-to-top.js ├── dark-mode.css ├── dark-mode.js ├── docsify-apachecn-footer.js ├── docsify-baidu-push.js ├── docsify-baidu-stat.js ├── docsify-clicker.js ├── docsify-cnzz.js ├── docsify-copy-code.min.js ├── docsify-quick-page.css ├── docsify-quick-page.js ├── docsify-sidebar-collapse.min.js ├── docsify.min.js ├── edit.css ├── edit.js ├── edit.svg ├── left.svg ├── lxgw-wenkai.css ├── moon.svg ├── prism-c.min.js ├── prism-cpp.min.js ├── prism-csharp.min.js ├── prism-darcula.css ├── prism-java.min.js ├── prism-javascript.min.js ├── prism-php.min.js ├── prism-python.min.js ├── right.svg ├── search.min.js ├── share.css ├── share.js ├── share.svg ├── sidebar.min.css ├── style.css ├── sun.svg ├── up.svg └── vue.css ├── docs ├── 10.md ├── 100.md ├── 101.md ├── 102.md ├── 103.md ├── 104.md ├── 105.md ├── 106.md ├── 107.md ├── 108.md ├── 109.md ├── 11.md ├── 110.md ├── 111.md ├── 112.md ├── 113.md ├── 114.md ├── 115.md ├── 116.md ├── 117.md ├── 118.md ├── 119.md ├── 12.md ├── 120.md ├── 121.md ├── 122.md ├── 123.md ├── 124.md ├── 125.md ├── 126.md ├── 127.md ├── 128.md ├── 129.md ├── 13.md ├── 130.md ├── 131.md ├── 133.md ├── 134.md ├── 135.md ├── 136.md ├── 137.md ├── 138.md ├── 139.md ├── 14.md ├── 141.md ├── 142.md ├── 143.md ├── 144.md ├── 145.md ├── 146.md ├── 147.md ├── 148.md ├── 149.md ├── 15.md ├── 150.md ├── 151.md ├── 152.md ├── 153.md ├── 154.md ├── 155.md ├── 156.md ├── 157.md ├── 158.md ├── 159.md ├── 16.md ├── 160.md ├── 161.md ├── 162.md ├── 163.md ├── 164.md ├── 165.md ├── 166.md ├── 167.md ├── 168.md ├── 169.md ├── 17.md ├── 170.md ├── 171.md ├── 172.md ├── 173.md ├── 174.md ├── 175.md ├── 176.md ├── 177.md ├── 178.md ├── 179.md ├── 18.md ├── 180.md ├── 181.md ├── 182.md ├── 183.md ├── 184.md ├── 185.md ├── 186.md ├── 187.md ├── 188.md ├── 189.md ├── 19.md ├── 190.md ├── 191.md ├── 192.md ├── 193.md ├── 194.md ├── 195.md ├── 196.md ├── 197.md ├── 198.md ├── 199.md ├── 2.md ├── 20.md ├── 200.md ├── 201.md ├── 202.md ├── 203.md ├── 204.md ├── 205.md ├── 206.md ├── 207.md ├── 208.md ├── 209.md ├── 21.md ├── 210.md ├── 211.md ├── 212.md ├── 213.md ├── 214.md ├── 215.md ├── 216.md ├── 217.md ├── 218.md ├── 219.md ├── 22.md ├── 220.md ├── 221.md ├── 222.md ├── 223.md ├── 224.md ├── 225.md ├── 226.md ├── 228.md ├── 229.md ├── 23.md ├── 230.md ├── 231.md ├── 232.md ├── 233.md ├── 234.md ├── 235.md ├── 236.md ├── 237.md ├── 238.md ├── 239.md ├── 24.md ├── 240.md ├── 25.md ├── 26.md ├── 27.md ├── 28.md ├── 29.md ├── 3.md ├── 30.md ├── 31.md ├── 32.md ├── 33.md ├── 34.md ├── 35.md ├── 36.md ├── 37.md ├── 38.md ├── 39.md ├── 4.md ├── 40.md ├── 41.md ├── 42.md ├── 43.md ├── 44.md ├── 45.md ├── 46.md ├── 47.md ├── 48.md ├── 49.md ├── 5.md ├── 50.md ├── 51.md ├── 52.md ├── 53.md ├── 54.md ├── 55.md ├── 56.md ├── 57.md ├── 58.md ├── 59.md ├── 6.md ├── 60.md ├── 61.md ├── 62.md ├── 63.md ├── 64.md ├── 65.md ├── 66.md ├── 67.md ├── 68.md ├── 69.md ├── 7.md ├── 70.md ├── 71.md ├── 72.md ├── 73.md ├── 74.md ├── 75.md ├── 76.md ├── 77.md ├── 78.md ├── 79.md ├── 8.md ├── 80.md ├── 81.md ├── 82.md ├── 83.md ├── 85.md ├── 86.md ├── 87.md ├── 88.md ├── 89.md ├── 9.md ├── 90.md ├── 91.md ├── 92.md ├── 93.md ├── 94.md ├── 95.md ├── 96.md ├── 97.md ├── 98.md ├── 99.md ├── img │ ├── +CgflAAAAABJRU5ErkJggg==.png │ ├── +Lrre58Fx5YAAAAABJRU5ErkJggg==.png │ ├── 0026f16969300456db8ec0612dc3b1ca.png │ ├── 04Q8pAAAAAElFTkSuQmCC.png │ ├── 04ec5f5aaf7562436d99bea598851dd5.png │ ├── 067574daeb04c6e628286d0bc8a4f553.png │ ├── 068294433ef8be6892813a2a22b1b150.png │ ├── 07e4ded44dff12fa5091f80cb2867b97.png │ ├── 0G48QFrzqd6AAAAAElFTkSuQmCC.png │ ├── 0c6aa671b17618008d41eda31583ba3e.png │ ├── 0fd0205a99709ad1918b4e192ca98ac9.png │ ├── 1.jpg │ ├── 1380533268_1067858732.jpg │ ├── 14gHxh0JuAAAAAElFTkSuQmCC.png │ ├── 154b45a417ce405d0c2d14cb5253db72.png │ ├── 15f084e81ed7dfc9c8cf7cc4f2fb3bbd.png │ ├── 198-1.png │ ├── 198-2.png │ ├── 1P2AAAAAElFTkSuQmCC.png │ ├── 1f15d76102e18f51d1d6080edbe3c8f5.png │ ├── 1fd70b06abdfd7fccccf418670fbe2e3.png │ ├── 1iZ8AAUzkUMAAAAAElFTkSuQmCC.png │ ├── 2.jpg │ ├── 2010102884819234.jpg │ ├── 201310160434378865.png │ ├── 20160729194328.jpg │ ├── 20160729194409.jpg │ ├── 20160729194437.jpg │ ├── 20160729194553.jpg │ ├── 20160729194627.jpg │ ├── 20160729194711.jpg │ ├── 20160729194734.jpg │ ├── 20160729194753.jpg │ ├── 20160729194812.jpg │ ├── 20160729194833.jpg │ ├── 20160729194927.jpg │ ├── 20160729195004.jpg │ ├── 20160729195037.jpg │ ├── 20160729195101.jpg │ ├── 20160729195139.jpg │ ├── 20160729201706.jpg │ ├── 20160729202107.jpg │ ├── 20160729202130.jpg │ ├── 20160729202148.jpg │ ├── 20160729202403.jpg │ ├── 20160729202654.jpg │ ├── 20160729203018.jpg │ ├── 20160729203052.jpg │ ├── 20160729203108.jpg │ ├── 20160729203641.jpg │ ├── 20160729203804.jpg │ ├── 20160729203923.jpg │ ├── 20160729204310.jpg │ ├── 20160729204446.jpg │ ├── 20160729204731.jpg │ ├── 20160729204833.jpg │ ├── 20160729204850.jpg │ ├── 20160729204908.jpg │ ├── 20160729204933.jpg │ ├── 20160729204953.jpg │ ├── 20160729205301.jpg │ ├── 20160729205328.jpg │ ├── 20160729205355.jpg │ ├── 20160729205604.jpg │ ├── 20160729205620.jpg │ ├── 20160729205638.jpg │ ├── 20160729205652.jpg │ ├── 20160729205710.jpg │ ├── 20160729205802.jpg │ ├── 20160729205830.jpg │ ├── 20160729212559.jpg │ ├── 20160729212616.jpg │ ├── 20160729212636.jpg │ ├── 20160729212700.jpg │ ├── 20160729212718.jpg │ ├── 20160729213225.jpg │ ├── 20160729213838.jpg │ ├── 20160730083455.jpg │ ├── 20160730085347.jpg │ ├── 20160730085449.jpg │ ├── 20160730085542.jpg │ ├── 20160730085721.jpg │ ├── 20160730090029.jpg │ ├── 20160730090124.jpg │ ├── 20160730090215.jpg │ ├── 20160730090339.jpg │ ├── 20160730091814.jpg │ ├── 20160730092229.jpg │ ├── 20160730103304.jpg │ ├── 20160730103602.jpg │ ├── 20160730103832.jpg │ ├── 20160730103935.jpg │ ├── 20160730104121.jpg │ ├── 20160730104230.jpg │ ├── 20160730104345.jpg │ ├── 20160730104621.jpg │ ├── 20160730104832.jpg │ ├── 20160730110148.jpg │ ├── 20160730110311.jpg │ ├── 20160730110502.jpg │ ├── 20160730110657.jpg │ ├── 20160730111454.jpg │ ├── 20160730111541.jpg │ ├── 20160730111850.jpg │ ├── 20160730111923.jpg │ ├── 20160730112101.jpg │ ├── 20160730112142.jpg │ ├── 20160730112308.jpg │ ├── 20160730112512.jpg │ ├── 20160730112558.jpg │ ├── 20160730112628.jpg │ ├── 20160730112859.jpg │ ├── 20160730112933.jpg │ ├── 20160730113110.jpg │ ├── 20160730113419.jpg │ ├── 20160730113450.jpg │ ├── 20160730113520.jpg │ ├── 20160730113539.jpg │ ├── 20160730113647.jpg │ ├── 20160730113722.jpg │ ├── 20160730113806.jpg │ ├── 20160730113941.jpg │ ├── 20160730114049.jpg │ ├── 20160730114142.jpg │ ├── 20160730114357.jpg │ ├── 20160730114542.jpg │ ├── 20160730145303.jpg │ ├── 20160730145708.jpg │ ├── 20160730145829.jpg │ ├── 20160730145913.jpg │ ├── 20160730150047.jpg │ ├── 20160730150200.jpg │ ├── 20160730150243.jpg │ ├── 20160730150337.jpg │ ├── 20160730150414.jpg │ ├── 20160730150548.jpg │ ├── 20160730150758.jpg │ ├── 20160730150825.jpg │ ├── 20160730151146.jpg │ ├── 20160730151234.jpg │ ├── 20160730151430.jpg │ ├── 20160730151519.jpg │ ├── 20160730152040.jpg │ ├── 20160730152146.jpg │ ├── 20160730152318.jpg │ ├── 20160730152420.jpg │ ├── 20160730152509.jpg │ ├── 20160730152558.jpg │ ├── 20160730152702.jpg │ ├── 20160730152739.jpg │ ├── 20160730152850.jpg │ ├── 20160730153020.jpg │ ├── 20160730153407.jpg │ ├── 20160730153526.jpg │ ├── 20160730153628.jpg │ ├── 20160730153716.jpg │ ├── 20160730153731.jpg │ ├── 20160730153815.jpg │ ├── 20160730154429.jpg │ ├── 20160730154447.jpg │ ├── 20160730154502.jpg │ ├── 20160730154518.jpg │ ├── 20160730154535.jpg │ ├── 20160730154556.jpg │ ├── 20160730154612.jpg │ ├── 20160730154641.jpg │ ├── 20160730154659.jpg │ ├── 20160730154719.jpg │ ├── 20160730154742.jpg │ ├── 20160730154811.jpg │ ├── 20160730161251.jpg │ ├── 20160730162015.jpg │ ├── 20160730162255.jpg │ ├── 20160730162332.jpg │ ├── 20160730162530.jpg │ ├── 20160730162636.jpg │ ├── 20160730162703.jpg │ ├── 20160730162735.jpg │ ├── 20160730162805.jpg │ ├── 20160730162902.jpg │ ├── 20160730163033.jpg │ ├── 20160730163120.jpg │ ├── 20160730163220.jpg │ ├── 20160730163350.jpg │ ├── 20160730163433.jpg │ ├── 20160730163527.jpg │ ├── 20160730163646.jpg │ ├── 20160730163745.jpg │ ├── 20160730163900.jpg │ ├── 20160730164002.jpg │ ├── 20160730164052.jpg │ ├── 20160730164649.jpg │ ├── 20160730165925.jpg │ ├── 20160730170018.jpg │ ├── 20160730170746.jpg │ ├── 20160730170924.jpg │ ├── 20160730172515.jpg │ ├── 20160730172648.jpg │ ├── 20160730172736.jpg │ ├── 20160730172841.jpg │ ├── 20160730172859.jpg │ ├── 20160730172924.jpg │ ├── 20160730173123.jpg │ ├── 20160730173418.jpg │ ├── 20160730173529.jpg │ ├── 20160730173827.jpg │ ├── 20160730173956.jpg │ ├── 20160730174030.jpg │ ├── 20160730174046.jpg │ ├── 20160730174101.jpg │ ├── 20160730174627.jpg │ ├── 20160730175219.jpg │ ├── 20160730175244.jpg │ ├── 20160730175839.jpg │ ├── 20160730175852.jpg │ ├── 20160730175909.jpg │ ├── 20160730180956.jpg │ ├── 20160730185015.jpg │ ├── 20160730185141.jpg │ ├── 20160730185157.jpg │ ├── 20160730185230.jpg │ ├── 20160730185408.jpg │ ├── 20160730185421.jpg │ ├── 20160730203352.jpg │ ├── 20160730205214.jpg │ ├── 20160730205244.jpg │ ├── 20160730205312.jpg │ ├── 20160730205616.jpg │ ├── 20160730211006.jpg │ ├── 20160730211028.jpg │ ├── 20160730213457.jpg │ ├── 209ea0d058dc8d7adaef102ed9b535f1.png │ ├── 229-1.png │ ├── 22d27be92f13241af230375dc437103c.png │ ├── 2531170_233756404000_2.jpg │ ├── 28cc5702182141ad9a4b8b932a8fcf7e.png │ ├── 2ead8b312ae7b51f29de3861e77e86d8.png │ ├── 2ecd884785dc3f4a51b4a34fd8a442ba.png │ ├── 3.jpg │ ├── 32caa5823cec72ad2a58f9dc0e2a595c.png │ ├── 4.jpg │ ├── 4103980b6ad518af52e473d098d77c6d.png │ ├── 4IZU2kAAAAASUVORK5CYII=.png │ ├── 4d1b62ce0e1d0cfe50ad3ee4cae18bf9.png │ ├── 4f22e7ea25464f9149f74e2fe33b69d4.png │ ├── 4fs3DDH2VdUggAAAAASUVORK5CYII=.png │ ├── 4sZSmjXStSQAAAABJRU5ErkJggg==.png │ ├── 52c434f8aa9bb3ab5889b17606576036.png │ ├── 5757480deeedaf0d9a461cf021baa404.png │ ├── 5XjiwKiPBhAAAAAASUVORK5CYII=.png │ ├── 5c75fc9165ac9c77fadc00270607e52a.png │ ├── 5mz5Zk3bgh6AAAAAElFTkSuQmCC.png │ ├── 63ef6a8dgw1et79vqchyfj20q20d90u3.jpg │ ├── 640.webp │ ├── 641.webp │ ├── 642.webp │ ├── 6631271175352063244.png │ ├── 6631305260212377879.jpg │ ├── 6631403116747394723.png │ ├── 6f06c1be5e15f1f73c1912d7b06cacd6.png │ ├── 78528393gw1eupdfv9tncj206i0bjgnj.jpg │ ├── 7c0aeae1a3d7d9163b81357bfbe47194.png │ ├── 7d10027dbe0ae32fc1e06540852150c0.png │ ├── 7f834b193087ef7f57100d5c3f33a54a.png │ ├── 886dcb9a9613c444f8c6a9c0139d8a80.png │ ├── 8DA9OsOjZhiiIAAAAASUVORK5CYII=.png │ ├── 8DjEAXQMXIa20AAAAASUVORK5CYII=.png │ ├── 8HQF+KVh4dTOYAAAAASUVORK5CYII=.png │ ├── 8HywGSQl4BhZYAAAAASUVORK5CYII=.png │ ├── 8Pd1ywPIOWNBEAAAAASUVORK5CYII=.png │ ├── 8abb7a7faabaaadc9810e25a47388ce1.png │ ├── 8fttfnnklLR34AAAAASUVORK5CYII=.png │ ├── 8ovCwcaAAAAAElFTkSuQmCC.png │ ├── 910ff562cf89f7d28018d1e0f304e3ed.png │ ├── 9133e63c0f3d2761c64297ad826dd4e0.png │ ├── 92812980c499198f79473c8e5bc34867.png │ ├── 984eaa662a3e7f4a890ffbc7882d4dd7.png │ ├── 9UgMOfNs0IoAAAAASUVORK5CYII=.png │ ├── 9Vb8bTa9LiAAAAAElFTkSuQmCC.png │ ├── 9a0d75c0b64801df5f788517507ca787.png │ ├── 9d5bd1920661f71d3c36b179ee35a5c5.png │ ├── 9hznwiJNAj8AAAAASUVORK5CYII=.png │ ├── A0AAAAAElFTkSuQmCC.png │ ├── A0eUsyP1FOrFAAAAAElFTkSuQmCC.png │ ├── A0lud6NxGMRtAAAAAElFTkSuQmCC.png │ ├── A48igGG8FAYYAAAAAElFTkSuQmCC.png │ ├── A8CZCFEIRc7cAAAAAElFTkSuQmCC.png │ ├── AAAAAElFTkSuQmCC.png │ ├── AL3KrJDuYcugAAAAAElFTkSuQmCC.png │ ├── AQ3T1iY4rBHBAAAAAElFTkSuQmCC.png │ ├── AQR5ZL9b230uAAAAAElFTkSuQmCC.png │ ├── ATuGB6iQQJk2AAAAAElFTkSuQmCC.png │ ├── AUDrTR8aw3gAAAAASUVORK5CYII=.png │ ├── AUVH1TAAAAAElFTkSuQmCC.png │ ├── AWAjkg9svLMnAAAAAElFTkSuQmCC.png │ ├── AbSpKHKNDdg4AAAAAElFTkSuQmCC.png │ ├── Abg8T0C992H2AAAAAElFTkSuQmCC.png │ ├── AfXMg1frdxFoAAAAAElFTkSuQmCC.png │ ├── B+ZopOJEidgZQAAAABJRU5ErkJggg==.png │ ├── B1g4ngqKGisJAAAAAElFTkSuQmCC.png │ ├── B2IkZZTnxoTNAAAAAElFTkSuQmCC.png │ ├── B2v5EoFCcb2OAAAAAElFTkSuQmCC.png │ ├── B8+jYCt0IQ19AAAAAElFTkSuQmCC.png │ ├── B9cWL8nbbmELAAAAAElFTkSuQmCC.png │ ├── CMKDJRIP9zQAAAAASUVORK5CYII=.png │ ├── D1WE+omWGBOYAAAAAElFTkSuQmCC.png │ ├── D5WvaLy+Zhg+AAAAAElFTkSuQmCC.png │ ├── D5tAx0AI6kX8AAAAAElFTkSuQmCC.png │ ├── D75GBxX7BcGLAAAAAElFTkSuQmCC.png │ ├── Dxn6FvydrLyNAAAAAElFTkSuQmCC.png │ ├── DxoulOujsI73AAAAAElFTkSuQmCC.png │ ├── Dz5W7ZaWGm6kAAAAAElFTkSuQmCC.png │ ├── DzC5GPf59h+kAAAAAElFTkSuQmCC.png │ ├── EVNbt5XyQAAAABJRU5ErkJggg==.png │ ├── H9sMnxW1nfoFAAAAAElFTkSuQmCC.png │ ├── HG01AAAAAElFTkSuQmCC.png │ ├── HZ~8C49.tmp │ ├── Hy+Xiz94AAAAASUVORK5CYII=.png │ ├── JCPjgCmIjjMAAAAASUVORK5CYII=.png │ ├── JYHOIIK4xSYAAAAASUVORK5CYII=.png │ ├── JjR1yOSNak8AAAAASUVORK5CYII=.png │ ├── K+CDPZh5cpEAAAAASUVORK5CYII=.png │ ├── KCTx9tZ5cAAAAAElFTkSuQmCC.png │ ├── LnkzUgN78ZoAAAAASUVORK5CYII=.png │ ├── MHO8b4v3jocAAAAASUVORK5CYII=.png │ ├── MqcClhxtsXgM8qWfcZM1sMLAG.png │ ├── QAAAAAElFTkSuQmCC.png │ ├── QH66R87Zb8AAAAABJRU5ErkJggg==.png │ ├── RDP_1.JPG │ ├── RDP_2.JPG │ ├── RDP_3.JPG │ ├── RDP_4.JPG │ ├── RDP_5.JPG │ ├── RDP_6.jpg │ ├── RwJAAAAAElFTkSuQmCC.png │ ├── RzxNFHjAAAAAElFTkSuQmCC.png │ ├── U+218cSH2BAAAAABJRU5ErkJggg==.png │ ├── UPRgcAAAAASUVORK5CYII=.png │ ├── UoLLwAAAAAElFTkSuQmCC.png │ ├── V4AAAAASUVORK5CYII=.png │ ├── V4f0G7Lv0AAAAASUVORK5CYII=.png │ ├── VNWoGenDKYQAAAABJRU5ErkJggg==.png │ ├── a6piEEhFmhgAAAAASUVORK5CYII=.png │ ├── aa0c1c3399986077fd0c0942f11b028b.png │ ├── abb45816d635b41d402defe54e045bd2.png │ ├── ae4e82ec233bfb292ded4be9bfc5665b.png │ ├── b38d62c5c7bb089547b053415aa8a1ca.png │ ├── bb7259cf07e434ed8728bae67b6e749e.png │ ├── c48c69740ac45e239ab3cfaeb52d0cd5.png │ ├── cu3AAAAAElFTkSuQmCC.png │ ├── d17632a412d2cb1faf08c738dc276847.png │ ├── d2jtewAAAAASUVORK5CYII=.png │ ├── d8JgNLeX0dwAAAABJRU5ErkJggg==.png │ ├── dab6c76c8769638e01b504a8afc8d1ff.png │ ├── ds14k2ysAAAAABJRU5ErkJggg==.png │ ├── e1599bb117e11bad7719d9d0bd9e024b.png │ ├── e26ac34da55c047982466e1ffda5ebd3.png │ ├── e68c425be5759a16144da57cd7ae7705.png │ ├── ead7bc5340d094251135f9366c52c657.png │ ├── ebe5e4a62c8fab9a0e9d9c5219538912.png │ ├── ef+Bm+eUB9U6M6OAAAAAElFTkSuQmCC.png │ ├── fNNIq41KFY0AAAAASUVORK5CYII=.png │ ├── features.png │ ├── g22pAAAAAElFTkSuQmCC.png │ ├── gPSGYhJvf3o4wAAAABJRU5ErkJggg==.png │ ├── h9WKfQXXyMLJQAAAABJRU5ErkJggg==.png │ ├── hc5EKcO8lx7jgAAAABJRU5ErkJggg==.png │ ├── hcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+H0Jf8PCkWn9o7i7uoAAAAASUVORK5CYII=.png │ ├── iO1.png │ ├── iVBORw0KGgoAAAANS.png │ ├── iVBORw0KGgoAAAANSUhEU.png │ ├── jHv3i474FsQAAAAASUVORK5CYII=.png │ ├── kgFFWfYfVAoAAAAASUVORK5CYII=.png │ ├── m47qtkWS6YwAAAABJRU5ErkJggg==.png │ ├── msNAxQAAAABJRU5ErkJggg==.png │ ├── n+ocSyhraj+egAAAABJRU5ErkJggg==.png │ ├── nfiQVqhg0XwAAAAASUVORK5CYII=.png │ ├── nqKj1oGodQgAAAAASUVORK5CYII=.png │ ├── ntdgUAAAAASUVORK5CYII=.png │ ├── oxmuDApUb1QAAAABJRU5ErkJggg==.png │ ├── pNAAAAAElFTkSuQmCC.png │ ├── plot_svm_regression_001.png │ ├── quote1.png │ ├── quote2.png │ ├── quote3.png │ ├── quote4.png │ ├── quote5.png │ ├── quote6.png │ ├── quote7.png │ ├── quote8.png │ ├── quote9.png │ ├── s4cKR2IsQAAAAASUVORK5CYII=.png │ ├── thalce+7plAAAAABJRU5ErkJggg==.png │ ├── tryLNzijMDoAAAAASUVORK5CYII=.png │ ├── u8GSZ4AIqcDojIAAAAASUVORK5CYII=.png │ ├── uOnjQAAAABJRU5ErkJggg==.png │ ├── ugprsBfAAAAAElFTkSuQmCC.png │ ├── uoLAAAAAElFTkSuQmCC.png │ ├── vFexPRHT3wAAAAAElFTkSuQmCC.png │ ├── vKxStvoSPoAAAAASUVORK5CYII=.png │ ├── w+5k7nU0WXiJQAAAABJRU5ErkJggg==.png │ ├── w88rXUSeExzJAAAAABJRU5ErkJggg==.png │ ├── w8vnpdrPXNWHQAAAABJRU5ErkJggg==.png │ ├── wCrdn1FNZ0wMQAAAABJRU5ErkJggg==.png │ ├── wEZucZM6U2+WgAAAABJRU5ErkJggg==.png │ ├── wEsjw2yCs52CAAAAABJRU5ErkJggg==.png │ ├── wFrvQlvEZv4fAAAAABJRU5ErkJggg==.png │ ├── wGVBSwUEnkkSgAAAABJRU5ErkJggg==.png │ ├── wGnXKnKn8ftmQAAAABJRU5ErkJggg==.png │ ├── wHJmyDTgAGuXgAAAABJRU5ErkJggg==.png │ ├── wHn1Ia2HAtWJAAAAABJRU5ErkJggg==.png │ ├── wJFQ9FqQJeCUgAAAABJRU5ErkJggg==.png │ ├── wNB0cTKVhhFFwAAAABJRU5ErkJggg==.png │ ├── wONpVaXQZFAEQAAAABJRU5ErkJggg==.png │ ├── wPCN4bV590OigAAAABJRU5ErkJggg==.png │ ├── wPDGGBLVtN+jQAAAABJRU5ErkJggg==.png │ ├── wZQaC3pZ2BQAAAAASUVORK5CYII=.png │ ├── wco1MUKbiiLrAAAAABJRU5ErkJggg==.png │ ├── wd2nc8Qv71Y0wAAAABJRU5ErkJggg==.png │ ├── wdneKxaJkj98AAAAABJRU5ErkJggg==.png │ ├── wfXtv1o1EKY1AAAAABJRU5ErkJggg==.png │ ├── wfcdzfNpYmSRQAAAABJRU5ErkJggg==.png │ ├── x2yIsPbxFhJAAAAAElFTkSuQmCC.png │ ├── x4cf6Dy6+oEAAAAAElFTkSuQmCC.png │ ├── x9eXbY6Y4pzRgAAAABJRU5ErkJggg==.png │ ├── xWBSVRXoNxUAAAAAElFTkSuQmCC.png │ ├── yk6mxLDAgNEAAAAASUVORK5CYII=.png │ ├── z9ZMF6h+69YrQAAAABJRU5ErkJggg==.png │ ├── zDAAAAAElFTkSuQmCC.png │ └── zwP8EhzWBsZAAAAAElFTkSuQmCC.png └── zhihu61854182.md ├── index.html ├── styles └── ebook.css └── update.sh /.gitignore: -------------------------------------------------------------------------------- 1 | _book 2 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/quant-learning/e75e946c54fd7444a152d3df9ae5f89a3d2bec9b/.nojekyll -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /404.html 3 | --- 4 | 5 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM httpd:2.4 2 | COPY ./ /usr/local/apache2/htdocs/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuantLearning 2 | 3 | > Python 量化交易教程整理 4 | > 5 | > 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 6 | > 7 | > 收割 SB 的人会被 SB 们封神,试图唤醒 SB 的人是 SB 眼中的 SB。——SB 第三定律 8 | 9 | * [在线阅读](https://qlearn.apachecn.org) 10 | * [在线阅读(Gitee)](https://apachecn.gitee.io/quant-learning/) 11 | * [ApacheCN 财务提升交流群 915394271](https://jq.qq.com/?_wv=1027&k=3b2GY1jt) 12 | * [ApacheCN 学习资源](http://www.apachecn.org/) 13 | 14 | ## DOCX:开放共享科研记录行动倡议 15 | 16 | 我们积极响应[科研开源计划(DOCX)](https://mmcheng.net/docx/)。如今开源不仅仅是开放源码,还包括数据集、模型、教程和实验记录。我们也在探讨其它类别的开源方案和协议。 17 | 18 | 希望大家了解这个倡议,把这个倡议与自己的兴趣点结合,做点力所能及的事情。每个人的微小的贡献,汇聚在一起就是整个开源生态。 19 | 20 | ## 联系方式 21 | 22 | ### 负责人 23 | 24 | * (虚位以待) 25 | 26 | ### 贡献者 27 | 28 | + [mushroomqiu](https://www.v2ex.com/member/mushroomqiu) 29 | + [飞龙](https://github.com/wizardforcel) 30 | 31 | ### 其他 32 | 33 | * 在我们的 [apachecn/quant-learning](https://github.com/apachecn/quant-learning) github 上提 issue. 34 | * 发邮件到 Email: `apachecn@163.com`. 35 | * 在我们的 [组织学习交流群](http://www.apachecn.org/organization/348.html) 中联系群主/管理员即可. 36 | 37 | ## 下载 38 | 39 | ### Docker 40 | 41 | ``` 42 | docker pull apachecn0/quant-learning 43 | docker run -tid -p :80 apachecn0/quant-learning 44 | # 访问 http://localhost:{port} 查看文档 45 | ``` 46 | 47 | ### PYPI 48 | 49 | ``` 50 | pip install quant-learning 51 | quant-learning 52 | # 访问 http://localhost:{port} 查看文档 53 | ``` 54 | 55 | ### NPM 56 | 57 | ``` 58 | npm install -g quant-learning 59 | quant-learning 60 | # 访问 http://localhost:{port} 查看文档 61 | ``` 62 | 63 | ## 其它协议 64 | 65 | 霞鹜文楷采用 [SIL 开放字体协议 1.1](https://github.com/lxgw/LxgwWenKai/blob/main/SIL_Open_Font_License_1.1.txt)。 66 | 67 | ## 赞助我们 68 | 69 | ![Donate](http://data.apachecn.org/img/about/donate.jpg) 70 | -------------------------------------------------------------------------------- /asset/LXGWWenKaiScreen.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/quant-learning/e75e946c54fd7444a152d3df9ae5f89a3d2bec9b/asset/LXGWWenKaiScreen.ttf -------------------------------------------------------------------------------- /asset/back-to-top.css: -------------------------------------------------------------------------------- 1 | #scroll-btn { 2 | position: fixed; 3 | right: 15px; 4 | bottom: 10px; 5 | width: 35px; 6 | height: 35px; 7 | background-repeat: no-repeat; 8 | background-size: cover; 9 | cursor: pointer; 10 | -webkit-user-select: none; 11 | -moz-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | background-image: url(up.svg); 15 | background-position-y: -1px; 16 | display: none; 17 | border: 2px solid; 18 | border-radius: 4px; 19 | } -------------------------------------------------------------------------------- /asset/back-to-top.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | var scrollBtn = document.createElement('div') 3 | scrollBtn.id = 'scroll-btn' 4 | document.body.append(scrollBtn) 5 | 6 | window.addEventListener('scroll', function() { 7 | var offset = window.document.documentElement.scrollTop; 8 | scrollBtn.style.display = offset >= 500 ? "block" : "none"; 9 | }) 10 | scrollBtn.addEventListener('click', function(e) { 11 | e.stopPropagation(); 12 | var step = window.scrollY / 15; 13 | var hdl = setInterval(function() { 14 | window.scrollTo(0, window.scrollY - step); 15 | if(window.scrollY <= 0) { 16 | clearInterval(hdl) 17 | } 18 | }, 15) 19 | }) 20 | }) -------------------------------------------------------------------------------- /asset/dark-mode.css: -------------------------------------------------------------------------------- 1 | #dark-mode-btn { 2 | position: fixed; 3 | right: 15px; 4 | top: 100px; 5 | width: 35px; 6 | height: 35px; 7 | background-repeat: no-repeat; 8 | background-size: cover; 9 | cursor: pointer; 10 | -webkit-user-select: none; 11 | -moz-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | transition: background-image .15s ease-in-out .15s; 15 | } 16 | 17 | .dark-logo { 18 | background-image: url('sun.svg'); 19 | } 20 | 21 | .light-logo { 22 | background-image: url('moon.svg'); 23 | } -------------------------------------------------------------------------------- /asset/dark-mode.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | var style = document.querySelector('#invert') 3 | if (style == null) { 4 | style = document.createElement('style') 5 | style.id = 'invert' 6 | document.head.append(style) 7 | } 8 | var btn = document.querySelector('#dark-mode-btn') 9 | if (btn == null) { 10 | btn = document.createElement('div') 11 | btn.id = 'dark-mode-btn' 12 | btn.classList.add('light-logo') 13 | document.body.append(btn) 14 | } 15 | 16 | var enableDarkMode = function() { 17 | style.innerText = 'html,img,pre,#dark-mode-btn{filter:invert(100%)}' 18 | btn.classList.remove('light-logo') 19 | btn.classList.add('dark-logo') 20 | localStorage.darkLight = 'dark' 21 | 22 | } 23 | var disableDarkMode = function() { 24 | style.innerText = '' 25 | btn.classList.remove('dark-logo') 26 | btn.classList.add('light-logo') 27 | localStorage.darkLight = 'light' 28 | } 29 | 30 | btn.addEventListener('click', function(){ 31 | var currMode = localStorage.darkLight || 'light' 32 | if (currMode == 'light') 33 | enableDarkMode() 34 | else 35 | disableDarkMode() 36 | }) 37 | 38 | if (localStorage.darkLight == 'dark') 39 | enableDarkMode() 40 | 41 | }) 42 | 43 | -------------------------------------------------------------------------------- /asset/docsify-apachecn-footer.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var cnzzId = window.$docsify.cnzzId 3 | var unRepo = window.$docsify.repo || '' 4 | var [un, repo] = unRepo.split('/') 5 | var footer = ` 6 |
7 |
8 |

我们一直在努力

9 |

${unRepo}

10 |

11 | 12 | 13 | iBooker 面试求职

14 |

15 |
16 | 20 |
21 |
22 | ` 23 | var plugin = function(hook) { 24 | hook.afterEach(function(html) { 25 | return html + footer 26 | }) 27 | hook.doneEach(function() { 28 | (adsbygoogle = window.adsbygoogle || []).push({}) 29 | }) 30 | } 31 | var plugins = window.$docsify.plugins || [] 32 | plugins.push(plugin) 33 | window.$docsify.plugins = plugins 34 | })() -------------------------------------------------------------------------------- /asset/docsify-baidu-push.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var plugin = function(hook) { 3 | hook.doneEach(function() { 4 | new Image().src = 5 | '//api.share.baidu.com/s.gif?r=' + 6 | encodeURIComponent(document.referrer) + 7 | "&l=" + encodeURIComponent(location.href) 8 | }) 9 | } 10 | var plugins = window.$docsify.plugins || [] 11 | plugins.push(plugin) 12 | window.$docsify.plugins = plugins 13 | })() -------------------------------------------------------------------------------- /asset/docsify-baidu-stat.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var plugin = function(hook) { 3 | hook.doneEach(function() { 4 | window._hmt = window._hmt || [] 5 | var hm = document.createElement("script") 6 | hm.src = "https://hm.baidu.com/hm.js?" + window.$docsify.bdStatId 7 | document.querySelector("article").appendChild(hm) 8 | }) 9 | } 10 | var plugins = window.$docsify.plugins || [] 11 | plugins.push(plugin) 12 | window.$docsify.plugins = plugins 13 | })() -------------------------------------------------------------------------------- /asset/docsify-cnzz.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var plugin = function(hook) { 3 | hook.doneEach(function() { 4 | var sc = document.createElement('script') 5 | sc.src = 'https://s5.cnzz.com/z_stat.php?id=' + 6 | window.$docsify.cnzzId + '&online=1&show=line' 7 | document.querySelector('article').appendChild(sc) 8 | }) 9 | } 10 | var plugins = window.$docsify.plugins || [] 11 | plugins.push(plugin) 12 | window.$docsify.plugins = plugins 13 | })() -------------------------------------------------------------------------------- /asset/docsify-quick-page.css: -------------------------------------------------------------------------------- 1 | #prev-page-button { 2 | position:fixed; 3 | top:140px; 4 | width: 35px; 5 | height: 35px; 6 | right: 15px; 7 | background-color: transparent; 8 | background-image: url(left.svg); 9 | background-repeat: no-repeat; 10 | background-size: cover; 11 | border:0; 12 | -webkit-user-select: none; 13 | -moz-user-select: none; 14 | -ms-user-select: none; 15 | user-select: none; 16 | outline:none; 17 | cursor: pointer; 18 | } 19 | 20 | #next-page-button { 21 | position:fixed; 22 | top:180px; 23 | width:35px; 24 | height:35px; 25 | right:15px; 26 | background-color: transparent; 27 | background-image: url(right.svg); 28 | background-repeat: no-repeat; 29 | background-size: cover; 30 | border:0; 31 | -webkit-user-select: none; 32 | -moz-user-select: none; 33 | -ms-user-select: none; 34 | user-select: none; 35 | outline:none; 36 | cursor: pointer; 37 | } -------------------------------------------------------------------------------- /asset/docsify-quick-page.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | var prevBtn = document.createElement("div") 3 | prevBtn.id = "prev-page-button" 4 | document.body.appendChild(prevBtn) 5 | var nextBtn = document.createElement("div"); 6 | nextBtn.id = "next-page-button" 7 | document.body.appendChild(nextBtn) 8 | 9 | var links = null 10 | var linkMap = null 11 | var getCurIdx = function() { 12 | if (!links) { 13 | links = Array 14 | .from(document.querySelectorAll(".sidebar-nav a")) 15 | .map(x => x.href) 16 | linkMap = {} 17 | links.forEach((x, i) => linkMap[x] = i) 18 | } 19 | 20 | var elem = document.querySelector(".active a") 21 | var curIdx = elem? linkMap[elem.href]: -1 22 | return curIdx 23 | } 24 | 25 | prevBtn.addEventListener('click', function () { 26 | if (!document.body.classList.contains('ready')) 27 | return 28 | var curIdx = getCurIdx() 29 | location.href = curIdx == -1? 30 | links[0]: 31 | links[(curIdx - 1 + links.length) % links.length] 32 | document.body.scrollIntoView() 33 | }, false) 34 | 35 | nextBtn.addEventListener('click', function () { 36 | if (!document.body.classList.contains('ready')) 37 | return 38 | var curIdx = getCurIdx() 39 | location.href = links[(curIdx + 1) % links.length] 40 | document.body.scrollIntoView() 41 | }, false) 42 | }) -------------------------------------------------------------------------------- /asset/edit.css: -------------------------------------------------------------------------------- 1 | #edit-btn { 2 | position: fixed; 3 | right: 15px; 4 | top: 260px; 5 | width: 35px; 6 | height: 35px; 7 | background-repeat: no-repeat; 8 | background-size: cover; 9 | cursor: pointer; 10 | -webkit-user-select: none; 11 | -moz-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | background-image: url(edit.svg); 15 | } -------------------------------------------------------------------------------- /asset/edit.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | var editBtn = document.createElement('div') 3 | editBtn.id = 'edit-btn' 4 | document.body.append(editBtn) 5 | 6 | var repo = window.$docsify.repo 7 | editBtn.addEventListener('click', function() { 8 | if (!repo) return 9 | if (!/https?:\/\//.exec(repo)) 10 | repo = 'https://github.com/' + repo 11 | var url = repo + '/tree/master' + 12 | location.hash.slice(1) + '.md' 13 | window.open(url) 14 | }) 15 | }) -------------------------------------------------------------------------------- /asset/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Edit 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /asset/left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1210 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /asset/lxgw-wenkai.css: -------------------------------------------------------------------------------- 1 | @font-face 2 | { 3 | font-family: lxgw-wenkai; 4 | src: url('LXGWWenKaiScreen.ttf'); 5 | } 6 | 7 | body 8 | { 9 | font-family: lxgw-wenkai !important; 10 | } 11 | -------------------------------------------------------------------------------- /asset/moon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /asset/prism-c.min.js: -------------------------------------------------------------------------------- 1 | Prism.languages.c=Prism.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+/,lookbehind:!0},keyword:/\b(?:__attribute__|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,function:/[a-z_]\w*(?=\s*\()/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],comment:Prism.languages.c.comment,directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean; -------------------------------------------------------------------------------- /asset/prism-cpp.min.js: -------------------------------------------------------------------------------- 1 | !function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/;e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)(?:[^;{}"'])+?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","operator",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); -------------------------------------------------------------------------------- /asset/prism-java.min.js: -------------------------------------------------------------------------------- 1 | !function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|null|open|opens|package|private|protected|provides|public|record|requires|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,a=/\b[A-Z](?:\w*[a-z]\w*)?\b/;e.languages.java=e.languages.extend("clike",{"class-name":[a,/\b[A-Z]\w*(?=\s+\w+\s*[;,=())])/],keyword:t,function:[e.languages.clike.function,{pattern:/(\:\:)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x[\da-f_]*\.?[\da-f_p+-]+\b|(?:\b\d[\d_]*\.?[\d_]*|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),e.languages.insertBefore("java","class-name",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0},namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism); -------------------------------------------------------------------------------- /asset/prism-python.min.js: -------------------------------------------------------------------------------- 1 | Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"string-interpolation":{pattern:/(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^\s*)@\w+(?:\.\w+)*/im,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; -------------------------------------------------------------------------------- /asset/right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1209 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /asset/share.css: -------------------------------------------------------------------------------- 1 | #share-btn { 2 | position: fixed; 3 | right: 15px; 4 | top: 220px; 5 | width: 35px; 6 | height: 35px; 7 | background-repeat: no-repeat; 8 | background-size: cover; 9 | cursor: pointer; 10 | -webkit-user-select: none; 11 | -moz-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | background-image: url('share.svg'); 15 | } -------------------------------------------------------------------------------- /asset/share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Share-1 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /asset/sidebar.min.css: -------------------------------------------------------------------------------- 1 | .sidebar-nav li{position:relative;margin:0;cursor:pointer}.sidebar-nav ul:not(.app-sub-sidebar)>li:not(.file)::before{content:'';display:block;position:absolute;top:11px;left:-12px;height:6px;width:6px;border-right:1px solid #505d6b;border-bottom:1px solid #505d6b;transform:rotate(-45deg);transition:transform .1s}.sidebar-nav ul:not(.app-sub-sidebar)>li.open::before{transform:rotate(45deg)}.sidebar-nav ul:not(.app-sub-sidebar)>li.collapse::before{transform:rotate(-45deg)} -------------------------------------------------------------------------------- /asset/style.css: -------------------------------------------------------------------------------- 1 | /*隐藏头部的目录*/ 2 | #main>ul:nth-child(1) { 3 | display: none; 4 | } 5 | 6 | #main>ul:nth-child(2) { 7 | display: none; 8 | } 9 | 10 | .markdown-section h1 { 11 | margin: 3rem 0 2rem 0; 12 | } 13 | 14 | .markdown-section h2 { 15 | margin: 2rem 0 1rem; 16 | } 17 | 18 | img, 19 | pre { 20 | border-radius: 8px; 21 | } 22 | 23 | .content, 24 | .sidebar, 25 | .markdown-section, 26 | body, 27 | .search input { 28 | background-color: rgba(243, 242, 238, 1) !important; 29 | } 30 | 31 | @media (min-width:600px) { 32 | .sidebar-toggle { 33 | background-color: #f3f2ee; 34 | } 35 | } 36 | 37 | .docsify-copy-code-button { 38 | background: #f8f8f8 !important; 39 | color: #7a7a7a !important; 40 | } 41 | 42 | body { 43 | /*font-family: Microsoft YaHei, Source Sans Pro, Helvetica Neue, Arial, sans-serif !important;*/ 44 | } 45 | 46 | .markdown-section>p { 47 | font-size: 16px !important; 48 | } 49 | 50 | .markdown-section pre>code { 51 | font-family: Consolas, Roboto Mono, Monaco, courier, monospace !important; 52 | font-size: .9rem !important; 53 | 54 | } 55 | 56 | /*.anchor span { 57 | color: rgb(66, 185, 131); 58 | }*/ 59 | 60 | section.cover h1 { 61 | margin: 0; 62 | } 63 | 64 | body>section>div.cover-main>ul>li>a { 65 | color: #42b983; 66 | } 67 | 68 | .markdown-section img { 69 | box-shadow: 7px 9px 10px #aaa !important; 70 | } 71 | 72 | 73 | pre { 74 | background-color: #f3f2ee !important; 75 | } 76 | 77 | @media (min-width:600px) { 78 | pre code { 79 | /*box-shadow: 2px 1px 20px 2px #aaa;*/ 80 | /*border-radius: 10px !important;*/ 81 | padding-left: 20px !important; 82 | } 83 | } 84 | 85 | @media (max-width:600px) { 86 | pre { 87 | padding-left: 0px !important; 88 | padding-right: 0px !important; 89 | } 90 | } 91 | 92 | .markdown-section pre { 93 | padding-left: 0 !important; 94 | padding-right: 0px !important; 95 | box-shadow: 2px 1px 20px 2px #aaa; 96 | } -------------------------------------------------------------------------------- /asset/sun.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /asset/up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1211 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/101.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 五 量化模型 4 | 5 | -------------------------------------------------------------------------------- /docs/102.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 5.1 动量模型 4 | 5 | -------------------------------------------------------------------------------- /docs/103.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Momentum策略 4 | 5 | > 来源:https://uqer.io/community/share/5526191ef9f06c8f33904571 6 | 7 | ```py 8 | import pandas as pd 9 | from pandas import Series, DataFrame 10 | 11 | start = datetime(2011, 1, 1) 12 | end = datetime(2014, 8, 1) 13 | benchmark = 'SH50' 14 | universe = set_universe('SH50') 15 | capital_base = 100000 16 | refresh_rate = 10 17 | 18 | window = 20 19 | 20 | def initialize(account): 21 | account.amount = 300 22 | add_history('hist', window) 23 | 24 | 25 | def handle_data(account): 26 | momentum = {'symbol':[], 'c_ret':[]} 27 | for stk in account.universe: 28 | momentum = pd.DataFrame(momentum) 29 | momentum = momentum.append([{'symbol':stk,'c_ret':account.hist[stk]['closePrice'].iloc[-1]/account.hist[stk]['closePrice'].iloc[0]}]) 30 | momentum = momentum.sort(columns='c_ret').reset_index(drop=True) 31 | momentum = momentum[len(momentum)*4/5:len(momentum)] 32 | buylist = momentum['symbol'].tolist() 33 | 34 | for stk in account.stkpos: 35 | if (stk not in buylist) and (account.stkpos[stk]>0): 36 | order_to(stk, 0) 37 | for stk in buylist: 38 | if account.stkpos.get(stk,0) == 0: 39 | order_to(stk, account.amount) 40 | ``` 41 | 42 | ![](img/20160730145303.jpg) 43 | 44 | -------------------------------------------------------------------------------- /docs/115.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Contrarian strategy 4 | 5 | > 来源:https://uqer.io/community/share/5545ff8df9f06c1c3d68802f 6 | 7 | Contrarian strategy similar with Momentum strategy 8 | 9 | ```py 10 | import pandas as pd 11 | start = '2010-01-01' # 回测起始时间 12 | end = '2015-01-01' # 回测结束时间 13 | benchmark = 'SH50' # 策略参考标准 14 | universe = set_universe('SH50') 15 | capital_base = 100000 # 起始资金 16 | longest_history = 40 # handle_data 函数中可以使用的历史数据最长窗口长度 17 | refresh_rate = 1 # 调仓频率,即每 refresh_rate 个交易日执行一次 handle_data() 函数 18 | 19 | 20 | def initialize(account): # 初始化虚拟账户状态 21 | pass 22 | 23 | def handle_data(account): # 每个交易日的买入卖出指令 24 | returndata = {'symbol':[], 'ret':[]} 25 | history_data = account.get_attribute_history('closePrice',40) 26 | for s in account.universe: 27 | returndata['symbol'].append(s) 28 | returndata['ret'].append(history_data[s][-1] / history_data[s][0]) 29 | returndatanew = pd.DataFrame(returndata).sort(columns = 'ret').reset_index() 30 | returndatanew = returndatanew[0:len(returndatanew)/5] 31 | buylist = returndatanew['symbol'].tolist() 32 | 33 | for cur in account.valid_secpos: 34 | if cur not in buylist: 35 | order_to(cur,0) 36 | for sym in buylist: 37 | if sym not in account.valid_secpos: 38 | order_to(sym,300) 39 | ``` 40 | 41 | ![](img/20160730151519.jpg) 42 | 43 | worse than Momentum strategy 44 | 45 | -------------------------------------------------------------------------------- /docs/118.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 5.4 决策树、随机树 4 | 5 | -------------------------------------------------------------------------------- /docs/122.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 5.6 海龟模型 4 | 5 | -------------------------------------------------------------------------------- /docs/123.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # simple turtle 4 | 5 | > 来源:https://uqer.io/community/share/55fe8f58f9f06c597165ef13 6 | 7 | ```py 8 | start = '2011-01-01' # 回测起始时间 9 | end = '2015-09-01' # 回测结束时间 10 | benchmark = 'HS300' # 策略参考标准 11 | universe = set_universe('HS300') # 证券池,支持股票和基金 12 | capital_base = 100000 # 起始资金 13 | freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 14 | refresh_rate = 1 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 15 | longest_history=60 16 | pos_pieces=10 17 | window=20 18 | 19 | def initialize(account): # 初始化虚拟账户状态 20 | pass 21 | 22 | def handle_data(account): # 每个交易日的买入卖出指令 23 | highest_price=account.get_attribute_history('highPrice',window) 24 | lowest_price=account.get_attribute_history('lowPrice',window) 25 | for stock in account.universe: 26 | current_price=account.referencePrice[stock] 27 | if current_price > highest_price[stock].max() and account.position.secpos.get(stock,0)==0: 28 | order_to(stock,capital_base/pos_pieces/current_price) 29 | elif current_price < lowest_price[stock].min(): 30 | order_to(stock,0) 31 | return 32 | ``` 33 | 34 | ![](img/20160730152509.jpg) 35 | 36 | -------------------------------------------------------------------------------- /docs/125.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 5.7 5217 策略 · 白龙马的新手策略 4 | 5 | > 来源:https://uqer.io/community/share/56458dbcf9f06c4446b480ec 6 | 7 | + 买入信号 :价格创出60个交易日新高,第二天买入 8 | 9 | + 卖出信号 :价格从最高点下跌17%,则第二天卖出 10 | 11 | + 卖出金额平均分配到新高的股价上 12 | 13 | ```py 14 | import numpy as np 15 | from datetime import datetime, timedelta 16 | 17 | start = '20120101' # 回测起始时间 18 | end = (datetime.today() - timedelta(days=1)).strftime('%Y%m%d') # 截止日期 19 | benchmark = 'HS300' # 策略参考标准 20 | universe = set_universe('HS300') 21 | capital_base = 1000000 # 起始资金 22 | freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 23 | refresh_rate = 1 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 24 | 25 | MAX_PRICE = {} 26 | 27 | def initialize(account): # 初始化虚拟账户状态 28 | pass 29 | 30 | def handle_data(account): # 每个交易日的买入卖出指令 31 | 32 | today = account.current_date.strftime('%Y%m%d') 33 | hist = account.get_attribute_history('closePrice' , 60) 34 | cash = account.cash 35 | buylist = [] 36 | 37 | #记录持仓股票的最高价(卖出判断指标) 38 | for s in account.valid_secpos : 39 | MAX_PRICE[s] = max(MAX_PRICE[s],np.max(hist[s])) 40 | 41 | # 备选买入股票,已经在股票池的股票不再重复购买,创60日新高则入选购买 42 | option = [x for x in account.universe if x not in account.valid_secpos] 43 | 44 | for s in option : 45 | if np.max(hist[s]) == hist[s][-1] : 46 | buylist.append(s) 47 | MAX_PRICE[s] = hist[s][-1] 48 | 49 | # 从最高点下跌17%,卖出 50 | for s in account.valid_secpos : 51 | 52 | if hist[s][-1] <= MAX_PRICE[s] * (1 - 0.17) : 53 | cash += hist[s][-1] * account.valid_secpos.get(s) 54 | order_to(s , 0) 55 | # 最高价清零 56 | MAX_PRICE[s] = 0 57 | 58 | # 买入 59 | for s in buylist : 60 | order( s, cash / len(buylist) / hist[s][-1] ) 61 | ``` 62 | 63 | ![](img/20160730152850.jpg) 64 | 65 | -------------------------------------------------------------------------------- /docs/127.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 5.9 神经网络 4 | 5 | -------------------------------------------------------------------------------- /docs/135.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 5.14 Z-score Model 4 | 5 | -------------------------------------------------------------------------------- /docs/137.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 信用债风险模型初探之:Z-Score Model 4 | 5 | > 来源:https://uqer.io/community/share/568b73d6228e5b67159bee69 6 | 7 | ## 0. 引言 8 | 9 | 2015年3月4日晚间,ST超日(上海超日太阳能科技股份有限公司)董事会发布公告称,“11超日债”本期利息将无法于原定付息日2014年3月7日按期全额支付。至此,“11超日债”正式成为国内首例违约债券。 10 | 11 | ## 1. 什么是 Zscore Model 12 | 13 | 简单的说,zscore model 是一种用于估计债券发行人违约风险的信用风险模型。 14 | 15 | ## 2. 本文提供的 Zscore Model 16 | 17 | 下面我们首先从原理,模型公式,划分区间三个方面来简单介绍一下本模块中的两个 Z-score 模型; 18 | 然后我们从如何获取数据,清洗数据;如何计算债券发行人 Z-score 值;如何作图来操练这个模型; 19 | 20 | ### 2.1 All Corporate Bonds 21 | 22 | 模型原理 23 | 24 | + 不需要发行人上市交易数据 25 | + 离散分析方法 26 | 27 | 模型公式 28 | 29 | ``` 30 | ZScore = 0.517 - 0.460*x1 + 9.320*2/x2 + 0.388*x3 + 1.158*x4 31 | 32 | x1: 负债合计/资产总计 33 | x2: 净利润/0.5*(资产总计 + 资产总计[上期]) 34 | x3: 营运资本/资产总计 35 | x4: 未分配利润/资产总计 36 | 37 | coef=[0.517, -0.460, 18.640, 0.388, 1.158] 38 | ``` 39 | 40 | 划分区间 41 | 42 | + `Z-score < 0.5`: 已经违约 43 | + `0.5 < Z-score < 0.9`: 有违约的可能性 44 | + `Z-score > 0.9`: 财务健康,短期内不会出现违约情况 45 | 46 | ### 2.2 Corporate Bonds with Equity Listings 47 | 48 | 模型原理 49 | 50 | + 需要发行人上市交易数据 51 | + 离散分析方法 52 | 53 | 模型公式 54 | 55 | ``` 56 | ZScore = 0.2086*x1 + 4.3465*x2 + 4.9601*x3 57 | 58 | x1: 总市值/负债合计 59 | x2: 营业总收入/资产总计 60 | x3: (资产总计-资产总计[上期])/资产总计[上期] 61 | 62 | coef = [0.2086, 4.3465, 4.9601] 63 | ``` 64 | 65 | 划分区间 66 | 67 | + `Z-score < 1.5408`: 已经违约 68 | + `Z-score > 1.5408`: 财务健康,短期内不会出现违约情况 69 | 70 | ## 3. 未来 71 | 72 | Z-Score 是一个比较基础,通用的模型,本文只是对其原理和实现的一个简单探索,要想真正 build 一个足够 robust 的模型还需要做很多工作。不过 uqer 提供了完善的财务数据,行情数据以及 100 多个相关因子,相信会给大家建立模型上节省不少时间。 73 | 74 | ```py 75 | # built-in package 76 | import time 77 | import json 78 | import random 79 | import datetime as dt 80 | 81 | # third-party package 82 | import numpy as np 83 | import pandas as pd 84 | pd.options.display.max_columns = 100 85 | pd.options.display.max_rows = 100 86 | from matplotlib.pyplot import * 87 | import seaborn 88 | 89 | -------------------------------------------------------------------------------- /docs/142.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 5.17 卡尔曼滤波 4 | 5 | > 来源:https://uqer.io/community/share/56324662f9f06c06acdb4762 6 | 7 | 有没有朋友懂如何用卡尔曼滤波进行金融数据分析的? 8 | 9 | 近来看了一些金融数据分析的资料。 10 | 其中有提到用卡尔曼滤波进行数据处理。 11 | 12 | 比如下面的文章: 13 | 14 | http://jonathankinlay.com/?p=1185 15 | 16 | 由于是EE背景,对滤波很有感情,所以看到卡尔曼滤波的处理方法,感觉很是兴奋。 17 | 18 | 但是文章没太懂,想找懂这块的朋友相互交流。 19 | 20 | 如果有相关书籍能够推荐就太好了。 21 | 22 | @llhe: 23 | 24 | 应该很好理解吧,配对交易很重要的是计算配对的比例,而比例是时变的,这就涉及到估计对冲系数的问题,卡尔曼滤波就是用来干这个的。我猜你简单的用滑动平均可能也可以的。刚开始学习,纸上谈兵多交流 25 | 26 | -------------------------------------------------------------------------------- /docs/143.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 5.18 LPPL anti-bubble model 4 | 5 | -------------------------------------------------------------------------------- /docs/144.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 今天大盘熔断大跌,后市如何—— based on LPPL anti-bubble model 4 | 5 | > 来源:https://uqer.io/community/share/568a65e0228e5b67159becfc 6 | 7 | + 今天指数两次熔断,沪深300大跌7%,很恐怖,我节前空仓,今天也就索性全部放逆回购了,这样后天才能赎回,也是为了防止明天万一想抄底剁手 8 | + 反正也是现成的算法调了调参数跑一跑,LPPL的anti-bubble model,感谢优矿平台 9 | + 今天大跌我想说一下我的想法,大跌原因不在熔断机制,而在于股价太贵了,没有足够的流动性支撑,熔断机制只是催化剂罢了。没有熔断,指数照样要冲不出3600,就想没有国家救市,指数照样能在2500点以上反弹一样(当然后期平台不会这么久)。 10 | 11 | ```py 12 | import lib.relppltool as relppltool 13 | from matplotlib import pyplot as plt 14 | import datetime 15 | import numpy as np 16 | import pandas as pd 17 | import seaborn as sns 18 | sns.set_style('white') 19 | 20 | limits = ([8.5, 8.6], [-0.25, -0.12], [-3, 3], [.15,.4], [0.05,0.1], [4,8], [0, 2*np.pi]) 21 | x = relppltool.Population(limits, 20, 0.3, 1.5, .05, 4) 22 | for i in range (3): 23 | x.Fitness() 24 | x.Eliminate() 25 | x.Mate() 26 | x.Mutate() 27 | 28 | x.Fitness() 29 | values = x.BestSolutions(3) 30 | for xx in values: 31 | print xx.PrintIndividual() 32 | ``` 33 | 34 | ```py 35 | data = pd.DataFrame({'Date':values[0].getDataSeries()[0],'Index':values[0].getDataSeries()[1],'Fit1':values[0].getExpData(),'Fit2':values[1].getExpData(),'Fit3':values[2].getExpData()}) 36 | data = data.set_index('Date') 37 | data.plot(figsize=(14,8)) 38 | 39 | 40 | ``` 41 | 42 | ![](img/oxmuDApUb1QAAAABJRU5ErkJggg==.png) 43 | 44 | 模型大家看看就好,权当参考。重点不在预测,而在资金管理。 45 | 46 | -------------------------------------------------------------------------------- /docs/146.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 六 大数据模型 4 | 5 | -------------------------------------------------------------------------------- /docs/147.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 6.1 市场情绪分析 4 | 5 | -------------------------------------------------------------------------------- /docs/148.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 通联情绪指标策略 4 | 5 | > 来源:https://uqer.io/community/share/548111daf9f06c8e7733670a 6 | 7 | ```py 8 | start = pd.datetime(2013, 11, 1) 9 | end = pd.datetime(2014, 11, 1) 10 | benchmark = 'HS300' 11 | universe = read('3b_ticker.txt').split(',') 12 | capital_base = 100000 13 | csvs = ['3b_news.csv'] 14 | 15 | def initialize(account): 16 | add_history('hist1', 1) 17 | 18 | def handle_data(account, data): 19 | for stock in universe: 20 | if (stock not in account.hist1) or ('emotion' not in account.hist1[stock].columns): 21 | continue 22 | 23 | sig = account.hist1[stock].iloc[0,:]['emotion'] 24 | if sig > 0.2 and account.position.stkpos.get(stock, 0)==0: 25 | order(stock, 100) 26 | elif sig < 0 and account.position.stkpos.get(stock, 0)>0: 27 | order_to(stock, 0) 28 | ``` 29 | 30 | ![](img/20160730161251.jpg) 31 | 32 | -------------------------------------------------------------------------------- /docs/150.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 6.2 新闻热点 4 | 5 | -------------------------------------------------------------------------------- /docs/153.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 七 排名选股系统 4 | 5 | -------------------------------------------------------------------------------- /docs/154.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 7.1 小市值投资法 4 | 5 | -------------------------------------------------------------------------------- /docs/159.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 10% smallest cap stock 4 | 5 | > 来源:https://uqer.io/community/share/5663e2f4f9f06c6c8a91b391 6 | 7 | ```py 8 | import numpy as np 9 | start = '2011-01-05' # 回测起始时间 10 | end = '2015-12-01' # 回测结束时间 11 | benchmark = 'HS300' # 策略参考标准 12 | universe = StockScreener(Factor.LCAP.nsmall(40)) 13 | capital_base = 100000 # 起始资金 14 | freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 15 | refresh_rate = 1 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 16 | 17 | def initialize(account): # 初始化虚拟账户状态 18 | account.empty = True 19 | 20 | def handle_data(account): # 每个交易日的买入卖出指令 21 | today = account.current_date 22 | if today.month == 12 and account.empty: 23 | account.empty = False 24 | for stock in account.universe: 25 | p = account.referencePrice.get(stock, 0) 26 | if np.isnan(p) or p == 0: 27 | continue 28 | order_pct_to(stock, 0.025) 29 | elif today.month == 4 and not account.empty: 30 | account.empty = True 31 | for stock in account.universe: 32 | if stock in account.valid_secpos: 33 | order_to(stock,0) 34 | ``` 35 | 36 | ![](img/20160730163120.jpg) 37 | 38 | -------------------------------------------------------------------------------- /docs/160.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 7.2 羊驼策略 4 | 5 | -------------------------------------------------------------------------------- /docs/165.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 7.3 低价策略 4 | 5 | -------------------------------------------------------------------------------- /docs/166.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 专捡便宜货(新版quartz) 4 | 5 | > 来源:https://uqer.io/community/share/55152e9ff9f06c8f33904450 6 | 7 | -------------------------------------------------------------------------------- /docs/167.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 策略原理 4 | 5 | 策略基本思路是:买入低于X元的股票, 持有到1.25X元以上则卖出. 6 | 7 | ```py 8 | start = datetime(2014, 6, 1) 9 | end = datetime(2015, 3, 27) 10 | benchmark = 'HS300' # 策略参考标准 11 | universe = set_universe('HS300') 12 | capital_base = 1000000 13 | 14 | 15 | def initialize(account): 16 | account.buy_price_flag = 4 17 | account.sell_price_flag = account.buy_price_flag*1.25 18 | 19 | def handle_data(account): 20 | signals = [] 21 | acc_cash = account.cash 22 | 23 | for stock in account.universe: 24 | 25 | p = account.referencePrice[stock] 26 | if p < account.buy_price_flag: 27 | #满足买入条件,加入signals列表中 28 | signals.append(stock) 29 | elif p >= account.sell_price_flag and account.secpos.get(stock, 0) > 0: 30 | #将卖出股票所得现金加入到本次的可用现金 31 | acc_cash += account.referencePrice[stock]*account.secpos.get(stock,0) 32 | order_to(stock, 0) 33 | 34 | for stock in signals: 35 | # 平均买入signals列表中的股票 36 | amount = acc_cash/len(signals)/account.referencePrice[stock] 37 | order(stock, amount) 38 | ``` 39 | 40 | ![](img/20160730163646.jpg) 41 | 42 | -------------------------------------------------------------------------------- /docs/169.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 八 轮动模型 4 | 5 | -------------------------------------------------------------------------------- /docs/170.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 8.1 大小盘轮动 · 新手上路 -- 二八ETF择时轮动策略2.0 4 | 5 | ```py 6 | start = '2013-05-01' # 回测起始时间 7 | end = '2015-09-01' # 回测结束时间 8 | benchmark = 'HS300' # 策略参考标准 9 | universe = ['510300.XSHG','510500.XSHG'] # 证券池,支持股票和基金 10 | HS300,SZ500=universe 11 | capital_base = 100000 # 起始资金 12 | freq = 'd' # 策略类型,'d'表示日间策略使用日线回测 13 | refresh_rate =1 # 调仓频率,表示执行handle_data的时间间隔,由于freq = 'd',时间间隔的单位为交易日 14 | max_retracement = 0.01 # 最大回撤比例 15 | 16 | def initialize(account): # 初始化虚拟账户状态 17 | pass 18 | 19 | def handle_data(account): # 每个交易日的买入卖出指令 20 | 21 | # 周末进行交换 22 | if account.current_date.weekday() != 4 : 23 | return 24 | 25 | # 有停牌的话,今天就跳过。 26 | if len(account.universe) < 2: return 27 | 28 | hist = account.get_attribute_history('closePrice', 19) 29 | if len(hist) < 2: 30 | return 31 | 32 | 33 | # 如果HS300四周内涨幅大于SZ500 34 | if hist[HS300][-1]/hist[HS300][0] > hist[SZ500][-1]/hist[ SZ500][0]: 35 | # 且为正收益 36 | if hist[HS300][-1]/hist[HS300][0] > 1: 37 | if account.avail_secpos.has_key(SZ500): 38 | order_pct_to(SZ500, 0) 39 | order_pct_to(HS300, 0.99) 40 | 41 | elif hist[HS300][-1]/hist[HS300][0] < 1- max_retracement: 42 | # 负收益,清盘 43 | if account.avail_secpos.has_key(SZ500): 44 | order_pct_to(SZ500, 0) 45 | if account.avail_secpos.has_key(HS300): 46 | order_pct_to(HS300, 0) 47 | 48 | 49 | 50 | # 如果HS300四周内涨幅小于SZ500 51 | elif hist[HS300][-1]/hist[HS300][0] < hist[SZ500][-1]/hist[ SZ500][0]: 52 | # 且为正收益 53 | if hist[SZ500][-1]/hist[SZ500][0] > 1: 54 | if account.avail_secpos.has_key(HS300): 55 | order_pct_to(HS300, 0) 56 | order_pct_to(SZ500, 0.99) 57 | 58 | elif hist[SZ500][-1]/hist[SZ500][0] < 1- max_retracement: 59 | # 负收益,清盘 60 | if account.avail_secpos.has_key(SZ500): 61 | order_pct_to(SZ500, 0) 62 | if account.avail_secpos.has_key(HS300): 63 | order_pct_to(HS300, 0) 64 | ``` 65 | 66 | ![](img/20160730163900.jpg) 67 | 68 | -------------------------------------------------------------------------------- /docs/171.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 8.2 季节性策略 4 | 5 | -------------------------------------------------------------------------------- /docs/172.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Halloween Cycle 4 | 5 | > 来源:https://uqer.io/community/share/5663db06f9f06c6c8a91b37c 6 | 7 | ```py 8 | import numpy as np 9 | start = '2006-01-01' # 回测起始时间 10 | end = '2015-12-01' # 回测结束时间 11 | benchmark = 'HS300' # 策略参考标准 12 | universe = ['601398.XSHG','600028.XSHG', '601988.XSHG', '600036.XSHG','600030.XSHG','601318.XSHG', '600000.XSHG', '600019.XSHG', '600519.XSHG', '601166.XSHG'] 13 | capital_base = 100000 # 起始资金 14 | freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 15 | refresh_rate = 1 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 16 | 17 | def initialize(account): # 初始化虚拟账户状态 18 | pass 19 | 20 | def handle_data(account): # 每个交易日的买入卖出指令 21 | today = account.current_date 22 | for stock in account.universe: 23 | if(today.month == 10): 24 | p = account.referencePrice.get(stock, 0) 25 | if np.isnan(p) or p == 0: 26 | continue 27 | order_pct_to(stock, 0.1) 28 | elif today.month == 5 and stock in account.valid_secpos: 29 | order_to(stock,0) 30 | ``` 31 | 32 | ![](img/20160730164002.jpg) 33 | 34 | -------------------------------------------------------------------------------- /docs/173.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Halloween cycle 2 4 | 5 | > 来源:https://uqer.io/community/share/54ae4117f9f06c276f651a07 6 | 7 | ## 策略思路 8 | 9 | “万圣节效应”:每年10月到次年5月,股票市场会出现上涨的趋势 10 | 11 | ## 策略实现 12 | 13 | + 股票池:流动性充足的10只个股,包括工商银行、中国石化等 14 | + 每年10月,将账户中现金平均分成10份,分别买入相应的10只个股,满仓;次年5月全部抛出,空仓 15 | 16 | ```py 17 | start = '2010-04-01' # 回测起始时间 18 | end = '2015-04-01' # 回测结束时间 19 | benchmark = 'HS300' # 策略参考标准 20 | # 证券池,流动性充足的10只个股 21 | universe = ['601398.XSHG', '600028.XSHG', '601988.XSHG', '600036.XSHG', '600030.XSHG', '601318.XSHG', '600000.XSHG', '600019.XSHG', '600519.XSHG', '601166.XSHG'] 22 | capital_base = 100000 # 起始资金 23 | longest_history = 1 # handle_data 函数中可以使用的历史数据最长窗口长度 24 | refresh_rate = 1 # 调仓频率,即每 refresh_rate 个交易日执行一次 handle_data() 函数 25 | 26 | def initialize(account): # 初始化虚拟账户状态 27 | pass 28 | 29 | def handle_data(account): # 每个交易日的买入卖出指令 30 | yesterday = account.get_attribute_history('closePrice',1) 31 | for stock in account.universe: 32 | today = account.current_date 33 | if stock not in account.valid_secpos and (today.month == 10): # 10月买入 34 | # 现金平均分成10份,买入 35 | amount = int(account.cash/len(account.universe)/ yesterday[stock][0]) 36 | order(stock, amount) 37 | 38 | elif stock in account.valid_secpos and (today.month == 5): # 5月卖出 39 | order_to(stock, 0) 40 | ``` 41 | 42 | ![](img/20160730164052.jpg) 43 | 44 | -------------------------------------------------------------------------------- /docs/176.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 8.3 行业轮动 4 | 5 | -------------------------------------------------------------------------------- /docs/177.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 银行股轮动 4 | 5 | > 来源:https://uqer.io/community/share/55d0314af9f06c915418c69a 6 | 7 | 策略说明:持续持有两支市净率最低银行股,每月换仓 8 | 9 | ```py 10 | import numpy as np 11 | import pandas as pd 12 | from pandas import DataFrame 13 | import datetime 14 | 15 | start = '2011-01-01' 16 | end = '2015-08-14' 17 | benchmark = 'HS300' 18 | universe = ['000001.XSHE','002142.XSHE','600000.XSHG','600015.XSHG','600016.XSHG','600036.XSHG','601009.XSHG','601166.XSHG','601169.XSHG','601288.XSHG','601328.XSHG','601398.XSHG','601818.XSHG','601939.XSHG','601988.XSHG','601998.XSHG'] 19 | 20 | capital_base = 10000000 21 | refresh_rate = 20 22 | 23 | def initialize(account): 24 | pass 25 | 26 | def handle_data(account): 27 | cal = Calendar('China.SSE') 28 | lastTDay = cal.advanceDate(account.current_date,'-1B',BizDayConvention.Preceding) 29 | today_str = lastTDay.strftime("%Y%m%d") 30 | 31 | tickers = [] 32 | for stk in account.universe: 33 | if not np.isnan(account.referencePrice[stk]): 34 | tickers.append(stk[0:6]) 35 | try: 36 | d=DataAPI.MktEqudGet(secID=u"",ticker=tickers,tradeDate=today_str,beginDate=u"",endDate=u"",field="secID,PB",pandas="1") 37 | 38 | d=d.sort(columns='PB',ascending=1) 39 | d=d.head(2) 40 | buylist = d['secID'].tolist() 41 | for stk in account.valid_secpos: 42 | if stk not in buylist: 43 | order_to(stk, 0) 44 | 45 | # 等权重买入所选股票 46 | portfolio_value = account.referencePortfolioValue 47 | 48 | for stk in buylist: 49 | if stk not in account.valid_secpos: 50 | order_to(stk, int(portfolio_value / account.referencePrice[stk] / 100.0 / len(buylist))*100) 51 | except: 52 | return 53 | 54 | ``` 55 | 56 | ![](img/20160730164649.jpg) 57 | 58 | -------------------------------------------------------------------------------- /docs/179.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 8.4 主题轮动 4 | 5 | -------------------------------------------------------------------------------- /docs/185.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 8.5 龙头轮动 4 | 5 | -------------------------------------------------------------------------------- /docs/189.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 九 组合投资 4 | 5 | -------------------------------------------------------------------------------- /docs/191.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 9.2 GMVP · Global Minimum Variance Portfolio (GMVP) 4 | 5 | > 来源:https://uqer.io/community/share/55461734f9f06c1c3d688030 6 | 7 | ```py 8 | import pandas as pd 9 | import numpy as np 10 | 11 | 12 | start = '2011-07-01' # 回测起始时间 13 | end = '2014-08-01' # 回测结束时间 14 | benchmark = 'SH50' # 策略参考标准 15 | universe = ['601398.XSHG','600028.XSHG', '601988.XSHG', '600036.XSHG','600030.XSHG','601318.XSHG', '600000.XSHG', '600019.XSHG', '600519.XSHG', '601166.XSHG'] 16 | capital_base = 100000 # 起始资金 17 | longest_history = 40 # handle_data 函数中可以使用的历史数据最长窗口长度 18 | refresh_rate = 10 # 调仓频率,即每 refresh_rate 个交易日执行一次 handle_data() 函数 19 | 20 | 21 | def initialize(account): # 初始化虚拟账户状态 22 | pass 23 | 24 | def handle_data(account): # 每个交易日的买入卖出指令 25 | history_data = account.get_attribute_history('closePrice',40) 26 | retmatrix = [] 27 | for s in account.universe: 28 | retmatrix.append([history_data[s][i]/ history_data[s][i - 1] for i in range(1,40) ]) 29 | retmatrix = np.array(retmatrix) 30 | covmatrix = np.cov(retmatrix, y=None, rowvar=1, bias=0, ddof=None) 31 | covmatrix = np.matrix(covmatrix) # 不加这句执行矩阵求逆报错 32 | covinv = np.linalg.inv(covmatrix) 33 | one_row = np.matrix(np.ones(len(account.universe))) 34 | one_vector = np.matrix(np.ones(len(account.universe))).transpose() 35 | up = np.dot(covinv, one_vector) 36 | down = np.dot(np.dot(one_row, covinv), one_vector) 37 | weights = up/down 38 | weightsum = 0 39 | for a in weights: 40 | weightsum += a 41 | index= 0 42 | for s in account.universe: 43 | weigh = weights[index]/weightsum 44 | index = index + 1 45 | amount = account.cash * weigh / account.referencePrice[s] 46 | order_to(s,amount) 47 | ``` 48 | 49 | ![](img/20160730172648.jpg) 50 | 51 | just implement the examples in the API doc 52 | 53 | -------------------------------------------------------------------------------- /docs/193.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 十 波动率 4 | 5 | -------------------------------------------------------------------------------- /docs/195.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 10.2 波动率择时 4 | 5 | -------------------------------------------------------------------------------- /docs/199.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 十一 算法交易 4 | 5 | -------------------------------------------------------------------------------- /docs/2.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 第一部分 新手入门 4 | 5 | -------------------------------------------------------------------------------- /docs/20.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 第二部分 股票量化相关 4 | 5 | -------------------------------------------------------------------------------- /docs/200.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 11.1 VWAP · Value-Weighted Average Price (VWAP) 4 | 5 | > 来源:https://uqer.io/community/share/55462234f9f06c1c3d688033 6 | 7 | You can find it in API doc 8 | 9 | ```py 10 | start = '2011-01-01' # 回测起始时间 11 | end = '2015-01-01' # 回测结束时间 12 | benchmark = 'SH50' # 策略参考标准 13 | universe = set_universe('SH50') 14 | capital_base = 100000 # 起始资金 15 | longest_history = 40 # handle_data 函数中可以使用的历史数据最长窗口长度 16 | refresh_rate = 1 # 调仓频率,即每 refresh_rate 个交易日执行一次 handle_data() 函数 17 | 18 | threshold = 0.03 19 | 20 | def initialize(account): # 初始化虚拟账户状态 21 | pass 22 | 23 | def handle_data(account): # 每个交易日的买入卖出指令 24 | for s in account.universe: 25 | try: 26 | inter = 20 27 | hist = account.get_symbol_history(s, inter) 28 | except: 29 | continue 30 | vwampvalue = sum(hist['turnoverValue'])/sum(hist['turnoverVol']) 31 | if(hist['lowPrice'][-1] < vwampvalue*(1 - threshold)) and (s not in account.valid_secpos): 32 | order(s,100) 33 | if(hist['lowPrice'][-1] > vwampvalue) and (s in account.valid_secpos): 34 | order_to(s,0) 35 | ``` 36 | 37 | ![](img/20160730174627.jpg) 38 | 39 | easy strategy.. bad results.... 40 | 41 | It's very difficult to get a good alpha...... 42 | 43 | -------------------------------------------------------------------------------- /docs/201.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 十二 中高频交易 4 | 5 | -------------------------------------------------------------------------------- /docs/203.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 12.2 日内交易 · 大盘日内走势 (for 择时) 4 | 5 | > 来源:https://uqer.io/community/share/5649b64af9f06c4446b48202 6 | 7 | 上周统计过周一到周五的涨跌分布,后来又统计了一下股指交割周的周四,竟然只有33.33%上涨 。也是醉了。 8 | 9 | 统计完日间,再来看下日内,那么大盘日内走势是怎样呢? 对日内操作有指导吗? 10 | 11 | 时间紧急,话不多说,上分析过程。 12 | 13 | ```py 14 | # 获取09年以来的上证交易日 15 | import datetime 16 | import seaborn 17 | import pandas as pd 18 | 19 | df = DataAPI.TradeCalGet(exchangeCD=u"XSHG",beginDate=u"20090101",endDate=datetime.datetime.now().strftime('%Y%m%d'),field=u"calendarDate,isOpen",pandas="1") 20 | trading_days = df[df.isOpen==1].calendarDate.apply(lambda x:x.replace('-','')).values 21 | trading_days 22 | 23 | array(['20090105', '20090106', '20090107', ..., '20151112', '20151113', 24 | '20151116'], dtype=object) 25 | ``` 26 | 27 | ```py 28 | # 获取09年以来的上证指数的分钟线 29 | df = None 30 | for date in trading_days: 31 | try: 32 | temp_df = DataAPI.MktBarHistOneDayGet(securityID='000001.XSHG',date=date, field='barTime,closePrice')[1:] 33 | except: 34 | print 'get data error at %s.' %date 35 | continue 36 | # 日内打分,1表示最高 37 | temp_df['rank'] = temp_df.closePrice.rank(ascending=False) 38 | temp_df['index'] = range(len(temp_df)) 39 | if df is None: 40 | df = temp_df 41 | else: 42 | df = df.append(temp_df) 43 | ``` 44 | 45 | 首先看一下30mins线,日内高点和低点的分布图。 46 | 47 | ```py 48 | bar_length = 30 #30mins bar 49 | def plot(bar_length): 50 | df['bar time'] = df['index'].apply(lambda x:x/bar_length) 51 | highest_count = df[df['rank'] == min(df['rank'])].groupby('bar time')['rank'].count() 52 | lowest_count = df[df['rank'] == max(df['rank'])].groupby('bar time')['rank'].count() 53 | 54 | pd.DataFrame({'highest point':highest_count,'lowest point': lowest_count}).plot(figsize=(14,8),kind='bar', title='%s mins bar' %bar_length) 55 | plot(bar_length) 56 | ``` 57 | 58 | ![](img/UoLLwAAAAAElFTkSuQmCC.png) 59 | 60 | 可以看到,日内的最高点和最低点在早盘和尾盘出现频率最高。实际上,确实很多人都会选择在早盘或者尾盘操作。 61 | 62 | 那15mins和5mins的情况呢? 63 | 64 | ```py 65 | plot(bar_length=15) 66 | plot(bar_length=5) 67 | ``` 68 | 69 | ![](img/DxoulOujsI73AAAAAElFTkSuQmCC.png) 70 | 71 | ![](img/Syhraj+egAAAABJRU5ErkJggg==.png) 72 | 73 | 5mins比15mins图更清晰。 74 | 75 | 越靠近开盘,出现日内低点概率越高;而越临近收盘,冲高概率也越高。极点微笑。 76 | 77 | 今天(20151116)的走势,正巧是低开高收。 78 | 79 | 对于日内需要调仓,或者做T,可以关注一下该现象。不做任何买卖建议哦。 80 | 81 | 完。 82 | 83 | -------------------------------------------------------------------------------- /docs/204.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 十三 Alternative Strategy 4 | 5 | -------------------------------------------------------------------------------- /docs/206.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 第三部分 基金、利率互换、固定收益类 4 | 5 | -------------------------------------------------------------------------------- /docs/207.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 一 分级基金 4 | 5 | -------------------------------------------------------------------------------- /docs/21.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 一 基本面分析 4 | 5 | -------------------------------------------------------------------------------- /docs/211.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 二 基金分析 4 | 5 | -------------------------------------------------------------------------------- /docs/213.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 三 债券 4 | 5 | -------------------------------------------------------------------------------- /docs/214.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 债券报价中的小陷阱 4 | 5 | > 来源:https://uqer.io/community/share/55361dc2f9f06c392662104e 6 | 7 | 投资者习惯于使用到期收益率作为衡量债券投资价值的标杆,倾向于买入收益率高的债券,卖出收益率低的债券。这里有一个隐含的假设,所有债券的到期收益率都是由同一算法计算而得。但是事实上,真的是这样吗? 8 | 9 | 上图是在2015年4月21日截取的中债登的实时行情。我们取其中一个债券做示例: 10 | 11 | + 代码:080014 12 | + 净价:100.363 13 | + 全价:103.214 14 | + 票息:4.23% 15 | + 到期收益率:3.019% 16 | 17 | 这个债券是2015年8月18日到期,还有一次付息。存续期不超过1年,为119天,0.326027年 18 | 19 | ## 1. 债券的例子 20 | 21 | ```py 22 | testBond = BuildBond('080014.XIBE') 23 | testBond.bondProfile() 24 | ``` 25 | 26 | 27 | | 080014.XIBE | 28 | | --- | 29 | | securityID | 080014.XIBE | 30 | | issuer | 财政部 | 31 | | issueDate | 2008-08-18 | 32 | | exchange | XIBE | 33 | | shortName | 08国债14 | 34 | | maturity | 7Y | 35 | | startDate | 2008-08-18 | 36 | | maturityDate | 2015-08-18 | 37 | | settlementDays | 1 | 38 | | coupon | 0.0423 | 39 | | frequency | 1 | 40 | | dayCounter | Actual/Actual (ISMA) | 41 | 42 | ```py 43 | cleanPrice = 100.363 44 | settlementDate = Date(2015,4,21) 45 | ``` 46 | 47 | ## 2. 简单利率算法 48 | 49 | ```py 50 | print u'到期收益率:%.4f' % (testBond.yieldFromCleanPrice(cleanPrice,'Actual/Actual (ISMA)', Compounding.Simple, Frequency.Annual, settlementDate)*100) 51 | print u'应计利息 :%.4f' % testBond.accruedAmount(Date(2015,4,21)) 52 | 53 | 到期收益率:3.0196 54 | 应计利息 :2.8509 55 | ``` 56 | 57 | ## 3. 复利算法 58 | 59 | ```py 60 | print u'到期收益率:%.4f' % (testBond.yieldFromCleanPrice(cleanPrice,'Actual/Actual (ISMA)', Compounding.Compounded, Frequency.Annual, settlementDate)*100) 61 | print u'应计利息 :%.4f' % testBond.accruedAmount(settlementDate) 62 | 63 | 到期收益率:3.0504 64 | 应计利息 :2.8509 65 | ``` 66 | 67 | ## 4. 总结 68 | 69 | 现阶段大多数行情软件的报价也都是依照中债登类似的做法。存续期少于1年的债券使用简单利率算法,大于1年的债券使用复利算法。同样的债券价格,使用不同的算法,获得的到期收益率会有些微的差异。这个差异在某个债券即将到期是特别明显(可能差几十个bp甚至上一个百分点)。所以投资者在使用到期收益率作为债券投资价值评估标准的时候,要注意这些差异。 70 | 71 | -------------------------------------------------------------------------------- /docs/215.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 四 利率互换 4 | 5 | -------------------------------------------------------------------------------- /docs/218.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 第四部分 衍生品相关 4 | 5 | -------------------------------------------------------------------------------- /docs/219.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 一 期权数据 4 | 5 | -------------------------------------------------------------------------------- /docs/22.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 1.1 alpha 多因子模型 4 | 5 | -------------------------------------------------------------------------------- /docs/222.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 二 期权系列 4 | 5 | -------------------------------------------------------------------------------- /docs/230.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 三 期权分析 4 | 5 | -------------------------------------------------------------------------------- /docs/239.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 四 期货分析 4 | 5 | -------------------------------------------------------------------------------- /docs/24.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 熔断不要怕, alpha model 为你保驾护航! 4 | 5 | > 来源:https://uqer.io/community/share/568df2a3228e5b18e4ba296e 6 | 7 | ## 事件回顾 8 | 9 | + 2016年1月7日,A股开盘半个小时收盘,A股周内第二次熔断,这次只花了15分钟。。。 10 | + 上证综指收报3115.89点,跌幅7.32%,成交额780亿元。 11 | + 深证成指收报10745.74点,跌幅8.35%,成交额1080亿元。 12 | + 创业板指收报2254.52点,跌幅8.66%,成交额261亿元。 13 | 14 | ## 贪婪与恐惧 15 | 16 | + 在宽松预期落空、宏观数据不佳、外盘不振、熔断机制的磁吸效应等众多因素的综合作用下,2016年迎来了开门黑天鹅 17 | 18 | + 抄底的抄底、加仓的加仓,无不演绎着资本市场的两大特色:贪婪与恐惧 19 | 20 | + 好在有段子手,喝上一碗鸡汤,看看周围人亏损情形也都一样,于是呵呵一笑,继续演绎着贪婪与恐惧 21 | 22 | ## 理性与思考 23 | 24 | + 虽然有着边际效应递减规律,但每次大跌带给我的痛是愈发厉害,因为真的痛了所以我才能真正静下心来思考与总结 25 | 26 | + 27 | 动荡的A股行情让我开始思考对投资风险的控制,单边持有多头/空头显然并不太适合A股,拿今天来说,倘若仅仅持有股票,那么亏损基本就在7%以上 28 | 29 | + 那么如何控制风险呢?是否需要考虑对冲风险?不追求超高的收益,只求稳稳当当,在A股频发黑天鹅的现状下只求稳健收益、睡个好觉 30 | 31 | ## 阿尔法对冲,穿越牛熊 32 | 33 | + 同时持有空头和多头,通过一定手段保证总体收益为正 34 | 35 | + 实际中,持有多头股票组合同时卖空股指期货,当大盘上涨时只要保证股票组合的收益大于股指期货的亏损就能实现整体盈利;同理,当大盘下跌时,保证股票的亏损小于股指期货的盈利就能实现整体正的收益 36 | 37 | + 长时间的累积,就能实现稳健的收益,无惧黑天鹅 38 | 39 | + 以今天为例,假设我股票多头亏损了6.9%,但期货端收益7%,从而整体我的收益是0.1%(7%-6.9%),试想,在别人亏损7%的时候我能实现盈利0.1%。。。 40 | 41 | 如下的例子,假设股票组合每天跑赢沪深300指数0.1%,看看长时间累积下来的情况如何 42 | 43 | ```py 44 | # 举例说明相对收益 45 | data = DataAPI.MktIdxdGet(ticker='000300', beginDate='20130101', field='tradeDate,CHGPct', pandas='1').set_index('tradeDate').rename(columns={'CHGPct':'benchmark'}) 46 | data['portfolio'] = data['benchmark'] + 0.001 # 每天跑赢基准0.1% 47 | data.cumsum().plot(figsize=(12,5)) 48 | 49 | 50 | ``` 51 | 52 | ![](img/gPSGYhJvf3o4wAAAABJRU5ErkJggg==.png) 53 | 54 | 如上图所示 55 | 56 | + 长时间累积下来,组合相比沪深300指数的超额收益是非常可观的,而且也是非常稳健的,2年时间的超额收益将近80%!!! 57 | + 而实际投资的阿尔法策略就是根据经济、金融理论,运用数学统计的方法,构建投资组合使其能够稳健跑赢基准指数(比如沪深300) 58 | + 在实际操盘中,也是买入股票,卖出股指期货 59 | 60 | ## 如何做阿尔法模型 61 | 62 | + 说了这么多,如何从研究到实盘,真正的做出一个阿尔法模型 63 | 64 | + 优矿社区里已经有手把手的教程量化分析师的Python日记 第14天:如何在优矿上做Alpha对冲模型 65 | 66 | + 每个月还有500万实盘大赛!!! 67 | 68 | 总结:受不来A股的跌宕起伏,只想睡个安稳的觉、做个安静的美男子,专心研究alpha model吧! 69 | 70 | -------------------------------------------------------------------------------- /docs/25.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 寻找 alpha 之: alpha 设计 4 | 5 | > 来源:https://uqer.io/community/share/56893bb1228e5b67159beb38 6 | 7 | ## 一.寻找alpha, 回测时相关误区: 8 | 9 | 1. insight back 过去没有现在这样全面的分析方法 10 | 2. data back 过去没有现在这样全面整理的数据来分析 11 | 3. computational power and technology 过去没有现在的计算能力和技术 12 | 13 | 以上三个因素只是影响预测准确率的众多因素之一. 14 | 15 | ## 二.寻找alpha, 如何确认某策略的规则失败: 16 | 17 | 1. 回撤大于正常水平 18 | 2. 夏普下降 19 | 3. 与其他已发现的有效规则冲突 20 | 21 | ## 三.寻找alpha, 22 | 23 | 多策略同时使用: 某策略在50%时间能正确预测价格, 假如有10条相同准确率的策略, 把它们同时应用起来会比使用单一更好. 24 | 25 | ## 四.策略分类 26 | 27 | 1. 日内alphas有以下两种: 28 | 1. 一定时间间隔的再平衡, 比如1/5/15分钟 29 | 1. 事件驱动再平衡 30 | 2. 日间alphas:以天为最小间隔的再平衡 31 | 2. 基于N天内数据 32 | 2. 基于当前的快照数据 33 | 2. 开盘/收盘 集合竞价时的交易 34 | 3. 周/月度的alphas 35 | 36 | ## 五 开发alpha 37 | 38 | 基于公开的信息, 找到其中的信号/模式, 这些数据处理过程越有效, 则alpha越好. 公开数据可以分为下面5个分类: 39 | 40 | 1. 量/价 使用技术分析对 量/价 做 预测/回归. 41 | 2. 基本面数据 42 | 3. 宏观数据 43 | 4. 各种文本数据:交易所公告, 公司公告, 报纸, 杂志, 新闻, 甚至社交媒体上的内容 44 | 5. 多媒体数据:音视频数据 45 | 46 | 有些数据并不能直接用来生成alpha, 但可以用来提高alpha的表现. 有下面3个例子: 47 | 48 | 1 风险因子模型: 通过控制风险因子甚至消除风险因子可以提高alpha的表现 49 | 2 关系模型: 不同票据之间在某种程度上有着关联, 在价格变动时有些是领跑的, 有些是被拖着跑的, 这些关联创造了套利的机会 50 | 3 微观模型: 提高真实交易执行中的表现 51 | 现在不是数据不够, 而是各种各样的数据太多了, 如何对数据消除噪音, 提取出我们要的信号. 问题的解决空间为非凸集, 断续, 动态. 我们可以对解决空间的范围的缩小就是通过不断使用已消化的结果来对新的数据进行处理. 52 | 53 | ## 六 评估alpha策略 54 | 55 | 1. 信息比率(Information Ratio) 持续表现怎样 56 | 2. 边际收益(Margin) =alpha带来的收益/交易次数, 可以得知交易次数对收效的影响, 值越高越好, 说明交易次数对收益影响越小. 57 | 3. 唯一性 与策略池里其他alpha相关性越低越好 58 | 59 | 当然还有其他测试方式来评估, 比如从票据流动性的好还是差还评估. 但记住, 对alpha的参数调整要以未来为目标, 因为就算你调整参数后, 对历史数据回测有多大提高也是没有用处的. 如果调整参数后对未来的预测贡献很小甚至负数, 但对历史数据却贡献很大, 那很可能是过度拟合了, 这时要用”样本外数据(out-of-sample data)”(机器学习里面有定义)来对alpha做评估, 而不能只是用”样本内数据(in-sample data)” 60 | 61 | -------------------------------------------------------------------------------- /docs/26.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 1.2 基本面因子选股 4 | 5 | -------------------------------------------------------------------------------- /docs/28.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ROE选股指标 4 | 5 | > 来源:https://uqer.io/community/share/5668533af9f06c6c8a91b688 6 | 7 | 简单的ROE选股:按ROE排序选前10%的股票,等权重买入 8 | 9 | ```py 10 | import numpy as np 11 | import pandas as pd 12 | start = '2015-01-01' # 回测起始时间 13 | end = '2016-01-01' # 回测结束时间 14 | benchmark = 'HS300' # 策略参考标准 15 | universe = set_universe('HS300') # 证券池,支持股票和基金 16 | capital_base = 100000 # 起始资金 17 | freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 18 | refresh_rate = 20 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 19 | 20 | 21 | 22 | def initialize(account): # 初始化虚拟账户状态 23 | pass 24 | 25 | def handle_data(account): # 每个交易日的买入卖出指令 26 | 27 | factor = DataAPI.MktStockFactorsOneDayGet(secID=account.universe,tradeDate=account.previous_date,field='secID,ROE',pandas="1").dropna() #获取所有股票的相关因子 28 | 29 | sec_val = {'symbol':[], 'factor_value':[]} 30 | 31 | for index, row in factor.iterrows(): 32 | sec_val['symbol'].append(row['secID']) 33 | sec_val['factor_value'].append(row['ROE']) 34 | 35 | sec_val = pd.DataFrame(sec_val).sort(columns='factor_value').reset_index() 36 | sec_val = sec_val[int(len(sec_val)*0.9):] #排序并选择前10% 37 | 38 | buylist = list(sec_val.symbol) #买入股票列表 39 | 40 | for stock in account.valid_secpos: 41 | if stock not in buylist: 42 | order_to(stock, 0) 43 | for stock in buylist: 44 | if stock not in account.valid_secpos: 45 | order(stock, account.cash/len(buylist)) 46 | return 47 | ``` 48 | 49 | ![](img/20160730085449.jpg) 50 | 51 | -------------------------------------------------------------------------------- /docs/3.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 一 量化投资视频学习课程 4 | 5 | > 来源:https://uqer.io/community/share/569c7068228e5b8ffc744fb3 6 | 7 | 优矿团队呕心力作的量化投资视频学习课程(第六课时已更新) 8 | 9 | 视频内容抢先看 10 | 11 | + [优矿界面介绍,使用向导](http://v.qq.com/page/f/j/d/f0179m7oujd.html) 12 | + [Python编程引导上](http://v.qq.com/page/i/m/k/i0179u46nmk.html) 13 | + [Python编程引导下](http://v.qq.com/page/y/0/t/y0180zz240t.html) 14 | + [DataAPI使用介绍](http://v.qq.com/page/x/9/a/x01813y499a.html) 15 | + [Quartz写策略介绍](http://v.qq.com/page/o/x/l/o0181o2vuxl.html) 16 | + [如何参加大赛(模拟交易),如何在社区分享策略](http://v.qq.com/page/h/w/l/h018670rwwl.html) 17 | + 社区精华帖介绍(上、下) 18 | 19 | 我们萌萌哒的量化分析师和美女经理都会在视频中以音频的形式跟大家打招呼,大家有什么问题和建议都可以在帖子下方留言,优矿小秘书欢迎大家随时来勾搭。 20 | 21 | 亲爱的优客们量化视频中的声音指标,你能分析出她是社区里的哪位大神嘛? 22 | 23 | -------------------------------------------------------------------------------- /docs/32.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 【基本面指标】Cash Cow 4 | 5 | > 来源:https://uqer.io/community/share/55418287f9f06c1c3d687fde 6 | 7 | ## 策略思路 8 | 9 | 每个季度,计算沪深300成分股资产负债表中的 现金及现金等价物/总资产 ,数值以最近一次披露的财报为准 10 | 11 | 清仓,选出该比率最大的前30只股票,将资金分成30份,分别买入 12 | 13 | 每60个交易日调仓一次 14 | 15 | ```py 16 | from heapq import nlargest 17 | from datetime import timedelta 18 | 19 | start = '2010-01-01' 20 | end = '2015-04-01' 21 | benchmark = 'HS300' 22 | universe = set_universe('HS300') 23 | capital_base = 500000 24 | refresh_rate = 60 25 | 26 | def initialize(account): 27 | pass 28 | 29 | def handle_data(account): 30 | cashpct = getCashPct(account.universe, account.current_date) 31 | buylist = nlargest(30, cashpct, key=cashpct.get) 32 | 33 | for stock in account.valid_secpos: 34 | order_to(stock, 0) 35 | 36 | for stock in buylist: 37 | order(stock, int(account.referencePortfolioValue/len(buylist)/account.referencePrice[stock]/100)*100) 38 | 39 | def getCashPct(universe, date): 40 | start, end = (date - timedelta(weeks=26)).strftime('%Y%m%d'), date.strftime('%Y%m%d') 41 | N = len(universe) 42 | if N == 0: 43 | return None 44 | elif N <= 45: 45 | batches = [universe] 46 | else: 47 | batches = [universe[i:i+45] for i in range(0, N, 45)] 48 | 49 | CashPct = {} 50 | for sub in batches: 51 | df = DataAPI.FdmtBSGet(secID=','.join(sub), publishDateBegin=start, publishDateEnd=end, field=['secID', 'cashCEquiv', 'TAssets']) 52 | for stock in sub: 53 | try: 54 | df_sub = df[df.secID==stock] 55 | df_sub['pct'] = df_sub['cashCEquiv'] / df_sub['TAssets'] 56 | CashPct[stock] = df_sub['pct'].mean() 57 | except: 58 | pass 59 | return CashPct 60 | ``` 61 | 62 | ![](img/20160730090124.jpg) 63 | 64 | -------------------------------------------------------------------------------- /docs/34.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 营业收入增长率+市盈率 4 | 5 | > 来源:https://uqer.io/community/share/568cd66e228e5b960b7fd252 6 | 7 | ## 策略思路: 8 | 9 | 买入A股中同时满足以下条件的股票: 10 | 11 | + 营业收入增长率最大的200只股票 12 | + 市盈率最低的200只股票 13 | 14 | 实际操作中,总是持有满足上述两个条件的股票集合的交集,按月调仓 15 | 16 | ```py 17 | start = '2015-01-01' # 回测起始时间 18 | end = '2016-01-01' # 回测结束时间 19 | benchmark = 'HS300' # 策略参考标准 20 | capital_base = 100000 # 起始资金 21 | freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 22 | refresh_rate = 20 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 23 | 24 | # 证券池,支持股票和基金 25 | # 股票池设为营业收入增长率最大的200只股票与市盈率最低的200只股票的交集 26 | universe = StockScreener(Factor.OperatingRevenueGrowRate.nlarge(200) & Factor.PE.nsmall(200)) 27 | 28 | def initialize(account): # 初始化虚拟账户状态 29 | pass 30 | 31 | def handle_data(account): # 每个交易日的买入卖出指令 32 | buylist = {stk:0 for stk in account.universe} 33 | 34 | # 不满足条件的股票,清仓 35 | for s in account.valid_secpos: 36 | if s not in buylist: 37 | order_to(s, 0) 38 | 39 | # 满足条件的股票,不管多少只,都等仓位买入 40 | v = account.referencePortfolioValue / len(buylist) # 每只股票买入金额 41 | for s in buylist: 42 | # 计算每只股票买卖股数: 正数为买入,负数为卖出 43 | buylist[s] = v / account.referencePrice[s] - account.valid_secpos.get(s, 0) 44 | 45 | for s in sorted(buylist, key=buylist.get): 46 | order(s, buylist[s]) 47 | ``` 48 | 49 | ![](img/20160730090339.jpg) 50 | 51 | -------------------------------------------------------------------------------- /docs/36.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 1.4 股东分析 4 | 5 | -------------------------------------------------------------------------------- /docs/4.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 二 Python 手把手教学 4 | 5 | -------------------------------------------------------------------------------- /docs/40.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 1.5 宏观研究 4 | 5 | -------------------------------------------------------------------------------- /docs/44.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 二 套利 4 | 5 | -------------------------------------------------------------------------------- /docs/45.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 2.1 配对交易 4 | 5 | -------------------------------------------------------------------------------- /docs/51.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 三 事件驱动 4 | 5 | -------------------------------------------------------------------------------- /docs/52.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 3.1 盈利预增 4 | 5 | -------------------------------------------------------------------------------- /docs/56.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 3.3 牛熊转换 4 | 5 | -------------------------------------------------------------------------------- /docs/57.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 历史总是相似 牛市还在延续 4 | 5 | > 来源:https://uqer.io/community/share/5541f07af9f06c1c3d687ffa 6 | 7 | 07年与15年的牛市时如此相似,你准备好继续all in 了吗? 8 | 9 | ## 话不多说,图见真章! 10 | 11 | ```py 12 | import datetime as dt 13 | import numpy as np 14 | import seaborn as sns 15 | sns.set_style('white') 16 | from matplotlib import pyplot as plt 17 | from CAL.PyCAL import * 18 | font.set_size(20) 19 | 20 | index = '000300' 21 | data = DataAPI.MktIdxdGet(ticker = index, beginDate='20070101', endDate='20071101') 22 | data.index = data.tradeDate.apply(lambda x: dt.datetime.strptime(x, '%Y-%m-%d')) 23 | 24 | data2 = DataAPI.MktIdxdGet(ticker =index, beginDate='20140830', endDate='20150428') 25 | data2.index = data2.tradeDate.apply(lambda x: dt.datetime.strptime(x, '%Y-%m-%d')) 26 | 27 | data['2006 - 2008'] = data['closeIndex'] 28 | data = data[['2006 - 2008']] 29 | data['2014 - 2015'] = np.nan 30 | data['2014 - 2015'][:len(data2.closeIndex.values)] = data2.closeIndex.values 31 | data = data[['2006 - 2008', '2014 - 2015']] 32 | data.plot(figsize=(8,4), grid = False) 33 | plt.legend([u'2007年牛市', u'2015年牛市'], prop = font, loc = 'best') 34 | sns.despine() 35 | ``` 36 | 37 | ![](img/AQ3T1iY4rBHBAAAAAElFTkSuQmCC.png) 38 | 39 | -------------------------------------------------------------------------------- /docs/58.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 历史总是相似 牛市已经见顶? 4 | 5 | > 来源:https://uqer.io/community/share/55814e7ef9f06c6519ad1522 6 | 7 | 本文是前文《历史总是相似 牛市还在延续》的续篇, 此文可点击下面的链接:历史总是相似 牛市还在延续 8 | 9 | ![](img/63ef6a8dgw1et79vqchyfj20q20d90u3.jpg) 10 | 11 | ## 话不多说,图见真章! 12 | 13 | 这次我们把比较的周期从2015年4月28日延续到2015年6月17日。现在两个月过去了,看到大盘的走势和07年那波牛市是相似的。按照相同的时间点,07年的大牛已经见顶,15年呢? 14 | 15 | ```py 16 | import datetime as dt 17 | import numpy as np 18 | import seaborn as sns 19 | sns.set_style('white') 20 | from matplotlib import pylab 21 | from CAL.PyCAL import * 22 | font.set_size(20) 23 | 24 | index = '000300' 25 | data = DataAPI.MktIdxdGet(ticker = index, beginDate='20070101', endDate='20071201') 26 | data.index = data.tradeDate.apply(lambda x: dt.datetime.strptime(x, '%Y-%m-%d')) 27 | 28 | data2 = DataAPI.MktIdxdGet(ticker =index, beginDate='20140830', endDate='20150617') 29 | data2.index = data2.tradeDate.apply(lambda x: dt.datetime.strptime(x, '%Y-%m-%d')) 30 | 31 | data['2006 - 2008'] = data['closeIndex'] 32 | data = data[['2006 - 2008']] 33 | data['2014 - 2015'] = np.nan 34 | data['2014 - 2015'][:len(data2.closeIndex.values)] = data2.closeIndex.values 35 | data = data[['2006 - 2008', '2014 - 2015']] 36 | data.plot(figsize=(16,8), grid = False) 37 | pylab.legend([u'2007年牛市', u'2015年牛市'], prop = font, loc = 'best') 38 | sns.despine() 39 | ``` 40 | 41 | ![](img/8HQF+KVh4dTOYAAAAASUVORK5CYII=.png) 42 | 43 | -------------------------------------------------------------------------------- /docs/62.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 四 技术分析 4 | 5 | -------------------------------------------------------------------------------- /docs/63.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4.1 布林带 4 | 5 | -------------------------------------------------------------------------------- /docs/65.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 布林带回调系统-日内 4 | 5 | > 来源:https://uqer.io/community/share/566929a4f9f06c6c8a91b6e6 6 | 7 | ```py 8 | import numpy as np 9 | import pandas as pd 10 | from pandas import DataFrame 11 | start = '2014-01-01' # 回测起始时间 12 | end = '2015-01-01' # 回测结束时间 13 | benchmark = 'HS300' # 策略参考标准 14 | universe = set_universe('HS300') # 证券池,支持股票和基金 15 | capital_base = 100000 # 起始资金 16 | freq = 'm' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 17 | refresh_rate = 239 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 18 | period = 10 19 | multiple=1.5 20 | threshold=-0.1 21 | boll=pd.DataFrame(index=universe,columns = ['mean_cp','high_channel','low_channel']) 22 | 23 | def initialize(account): # 初始化虚拟账户状态 24 | pass 25 | 26 | def handle_data(account): # 每个交易日的买入卖出指令 27 | if(account.current_minute=='09:30'): 28 | close_prices = account.get_daily_attribute_history('closePrice', period) 29 | for s in account.universe: 30 | mean_cp = close_prices[s].mean() 31 | bias = multiple*np.std(close_prices[s]) 32 | high_channel = mean_cp + bias 33 | low_channel = mean_cp - bias 34 | boll.at[s,'high_channel']=high_channel 35 | boll.at[s,'low_channel']=low_channel 36 | boll.at[s,'mean_cp']=mean_cp 37 | elif(account.current_minute=='14:50'): 38 | print account.current_date,",",account.valid_secpos 39 | else: 40 | for s in account.valid_secpos: #清仓 41 | if account.referencePrice[s]>=boll.at[s,'mean_cp'] : 42 | order_to(s, 0) 43 | buylist=[] 44 | c = account.referencePortfolioValue 45 | for s in account.universe: 46 | if ((account.referencePrice[s]-boll.at[s,'low_channel'])/boll.at[s,'low_channel'])<=threshold: 47 | buylist.append(s) 48 | if (len(buylist)==0): 49 | return 50 | else: 51 | w=min(0.2,1.0/len(buylist))# 最大仓位1/5 52 | for s in buylist: 53 | p=account.referencePrice[s]*1.01 54 | num=int(c * w / p) 55 | order(s, num) 56 | 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /docs/69.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4.2 均线系统 4 | 5 | -------------------------------------------------------------------------------- /docs/73.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # macross 4 | 5 | > 来源:https://uqer.io/community/share/55a92cdcf9f06c57a11b53be 6 | 7 | ```py 8 | #第一次写大家帮看看有问题么 9 | #策略 : 日收盘价高于ma20 买入; 低于ma20 卖出清仓 10 | from matplotlib import pylab 11 | import numpy as np 12 | import pandas as pd 13 | import DataAPI 14 | import seaborn as sns 15 | sns.set_style('white') 16 | ################ 17 | 18 | start = datetime(2008, 1, 1) # 回测起始时间 19 | end = datetime(2015, 4, 23) # 回测结束时间 20 | benchmark = 'SH50' # 策略参考标准 21 | universe = ['510050.XSHG'] # 股票池 22 | #benchmark = 'HS300' 23 | #universe = ['510300.XSHG'] 24 | capital_base = 100000 # 起始资金 25 | commission = Commission(0.0,0.0) 26 | 27 | window_short = 20 28 | window_long = 300 29 | longest_history = window_long 30 | #longest_history = window_short 31 | SD = 0.05 32 | 33 | def initialize(account): # 初始化虚拟账户状态 34 | account.fund = universe[0] 35 | account.SD = SD 36 | account.window_short = window_short 37 | account.window_long = window_long 38 | 39 | def handle_data(account): # 每个交易日的买入卖出指令 40 | hist = account.get_history(longest_history) 41 | fund = account.fund 42 | short_mean = np.mean(hist[fund]['closePrice'][-account.window_short:]) # 计算短均线值 43 | long_mean = np.mean(hist[fund]['closePrice'][-account.window_long:]) #计算长均线值 44 | now_price = hist[fund]['closePrice'][-1:] 45 | #print len(short_mean) 46 | #print type(now_price) 47 | #print(now_price) 48 | 49 | #now_price.plot 50 | #all_close_prices = account.get_attribute_history('closePrice', 1) 51 | 52 | # 计算买入卖出信号 53 | # flag = True if (short_mean - long_mean) > account.SD * long_mean else False 54 | flag = True if (now_price - short_mean) > account.SD * short_mean else False 55 | if flag: 56 | if account.position.secpos.get(fund, 0) == 0: 57 | # 空仓时全仓买入,买入股数为100的整数倍 58 | approximationAmount = int(account.cash / hist[fund]['closePrice'][-1]/100.0) * 100 59 | order(fund, approximationAmount) 60 | else: 61 | # 卖出时,全仓清空 62 | if account.position.secpos.get(fund, 0) >= 0: 63 | order_to(fund, 0) 64 | ``` 65 | 66 | ![](img/20160730111923.jpg) 67 | 68 | -------------------------------------------------------------------------------- /docs/74.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4.3 MACD 4 | 5 | -------------------------------------------------------------------------------- /docs/80.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4.6 RSI 4 | 5 | -------------------------------------------------------------------------------- /docs/82.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # RSI指标策略 4 | 5 | > 来源:https://uqer.io/community/share/549ccfd2f9f06c4bb886323d 6 | 7 | ## 策略思路 8 | 9 | + 使用talib中的RSI函数计算每只股票过去20天的rsi 10 | + 当rsi低于30是买入,高于70时卖出 11 | + 每只股票仓位最多不超过总资金的10% 12 | 13 | ```py 14 | import talib as ta 15 | 16 | start = '2011-12-01' 17 | end = '2015-04-01' 18 | 19 | benchmark = 'SH50' 20 | universe = set_universe('SH50') 21 | capital_base = 5000000 22 | longest_history = 21 23 | 24 | def initialize(account): 25 | account.lower_rsi = 30 26 | account.upper_rsi = 70 27 | 28 | def handle_data(account): 29 | all_close_prices = account.get_attribute_history('closePrice', longest_history) 30 | 31 | rsi, c_price, c_amount = {}, {}, {} 32 | for stock in account.universe: 33 | rsi[stock] = ta.RSI(all_close_prices[stock], longest_history-1)[-1] 34 | c_amount[stock] = account.secpos.get(stock, 0) 35 | 36 | for stock in account.universe: 37 | max_amount = int(0.1 * account.referencePortfolioValue / account.referencePrice[stock]) 38 | amount = min(int(25000./account.referencePrice[stock]), max_amount - c_amount[stock]) 39 | if (rsi[stock] < account.lower_rsi) and (c_amount[stock] < max_amount): 40 | order(stock, amount) 41 | elif (rsi[stock] > account.upper_rsi) and (c_amount[stock] > 0): 42 | order_to(stock, 0) 43 | ``` 44 | 45 | ![](img/20160730113110.jpg) 46 | 47 | -------------------------------------------------------------------------------- /docs/87.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4.10 CMO 4 | 5 | -------------------------------------------------------------------------------- /docs/89.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # CMO策略模仿练习2 4 | 5 | > 来源:https://uqer.io/community/share/55b4e523f9f06c91f918c5db 6 | 7 | ```py 8 | import numpy as np 9 | 10 | start='2010-01-01' 11 | end='2015-06-20' 12 | benchmark='SH50' 13 | universe=set_universe('SH50') 14 | capital_base=1000000 15 | window=35 # 参数,CMO指标计算周期 16 | def initialize(account): 17 | pass 18 | def handle_data(account): 19 | clp=account.get_attribute_history("closePrice",window) 20 | prc=account.get_attribute_history("preClosePrice",window) 21 | p=account.referencePrice 22 | # 计算CMO 23 | CMO= {} 24 | for s in account.universe: 25 | diff=clp[s]-prc[s] 26 | u=sum(n for n in diff if n>0) 27 | d=sum(-n for n in diff if n<0) 28 | if u+d==0: continue 29 | CMO[s]=(u-d)/(u+d)*100 30 | # 根据CMO卖出目前持有股票 31 | v=account.cash 32 | for s,a in account.valid_secpos.items(): 33 | if CMO.get(s,0)<0 and s in account.universe: 34 | order_to(s,0) 35 | v+=a*p[s] 36 | # 根据CMO确定买入列表 37 | buylist= [] 38 | for s in account.universe: 39 | if CMO.get(s,0)<0 and not np.isnan(p[s]) and s not in account.valid_secpos: 40 | buylist.append(s) 41 | if v > account.referencePortfolioValue * 0.33: # 为了避免调仓过于频繁,仅当可用现金超过账户市值1/3时买入 42 | for s in buylist: 43 | order(s, v/len(buylist)/ p[s]) 44 | ``` 45 | 46 | ![](img/20160730113941.jpg) 47 | 48 | -------------------------------------------------------------------------------- /docs/92.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4.12 Chaikin Volatility 4 | 5 | -------------------------------------------------------------------------------- /docs/93.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 嘉庆离散指标测试 4 | 5 | > 来源:https://uqer.io/community/share/55595229f9f06c6c7104f8b3 6 | 7 | ```py 8 | import numpy as np 9 | start = datetime(2011, 1, 1) 10 | end = datetime(2015, 4, 27) 11 | benchmark = 'HS300' 12 | universe = set_universe('HS300') 13 | capital_base = 100000 14 | short_history = 30 15 | longest_history = 60 16 | 17 | pos_pieces = 10 18 | enter_window = 20 19 | exit_window = 10 20 | N = 4 21 | 22 | def initialize(account): 23 | account.postion_size_hold = {} 24 | for stk in universe: 25 | account.postion_size_hold[stk] = 0 26 | 27 | def handle_data(account): 28 | for stock in account.universe: 29 | cnt_price = account.referencePrice[stock] 30 | a1 = account.get_attribute_history('closePrice', longest_history)[stock]-account.get_attribute_history('lowPrice', longest_history)[stock] 31 | b1 = account.get_attribute_history('closePrice', longest_history)[stock]-account.get_attribute_history('highPrice',longest_history)[stock] 32 | c1 = account.get_attribute_history('highPrice',longest_history)[stock]-account.get_attribute_history('lowPrice',longest_history)[stock] 33 | d1 = account.get_attribute_history('turnoverVol', longest_history)[stock] 34 | adl = ((((a1)-(b1))/(c1)))*d1 35 | a2 = account.get_attribute_history('closePrice', short_history)[stock]-account.get_attribute_history('lowPrice', short_history)[stock] 36 | b2 = account.get_attribute_history('closePrice', short_history)[stock]-account.get_attribute_history('highPrice',short_history)[stock] 37 | c2 = account.get_attribute_history('highPrice',short_history)[stock]-account.get_attribute_history('lowPrice',short_history)[stock] 38 | d2 = account.get_attribute_history('turnoverVol', short_history)[stock] 39 | ads = ((((a2)-(b2))/(c2)))*d2 40 | 41 | mean_cp1 = adl.mean() 42 | mean_cp2 = ads.mean() 43 | 44 | flag = mean_cp1 - mean_cp2 45 | if flag > 0 and account.postion_size_hold[stock]