{"_id":"@cmike444/supply-and-demand-zones","_rev":"14-198ce7f9810685f935c78d4b7afef892","name":"@cmike444/supply-and-demand-zones","dist-tags":{"latest":"1.3.1"},"versions":{"1.0.0":{"name":"@cmike444/supply-and-demand-zones","version":"1.0.0","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.0.0","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"dist":{"shasum":"cc65b607ae794ddaf302ab6f360204389643e021","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.0.0.tgz","fileCount":48,"integrity":"sha512-h0f5OFFtsts9T75yY+Cntq7jwjMQZGMHJCgiiz+6S65egZpU0uveNslkFNkNXoAVsPVTf0IkDYS20mWdjk3rcA==","signatures":[{"sig":"MEQCICk0L79P3Jyl/TGiT/AcWKPi8mn0Stuv99C1eYJ3pQpyAiAUHWox4qwxk+Fgu2gy5iGsxhcZmQVW9CZysibEJg7d3A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43536},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"4934f70e0daf02850d56a825f876c0aa89dc4c12","scripts":{"test":"jest","build":"tsc","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"_npmVersion":"9.5.1","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"18.14.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.0.0_1746297554112_0.6749017804362978","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@cmike444/supply-and-demand-zones","version":"1.0.2","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.0.2","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/chrismikelson/SupplyAndDemand#readme","bugs":{"url":"https://github.com/chrismikelson/SupplyAndDemand/issues"},"dist":{"shasum":"2224c849017425abd5c94922a6b6ab9cc09c9660","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.0.2.tgz","fileCount":2,"integrity":"sha512-+i51wyVVGQUsqo739ni/pAADQj+nTCgSGV3VGLxq0WKbrT/BrBgqapMW98Oj7Q+8KMbT2HB+r8PLhKtn3ydpHQ==","signatures":[{"sig":"MEYCIQD5eM3wjYu1cqS3+NYIqBlIKGL9ELVoLOhwkfua1+L5ugIhAKW5emAM3spJPV65nTn1SrQziLj+UyeMWo5GJ0hseA+h","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":4715},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"6e8d2d4a0b11e10f93d86625c8c114c5967be4fa","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/chrismikelson/SupplyAndDemand.git","type":"git"},"_npmVersion":"8.19.4","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"16.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.0.2_1746379797673_0.8355060663609306","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@cmike444/supply-and-demand-zones","version":"1.0.3","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.0.3","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"c1ff1c68f9c1fe02baa0dbca7a8ea144d5be44b7","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.0.3.tgz","fileCount":2,"integrity":"sha512-ldNDO5lRiH04UkY/ZhpiRfaiLugeYO3s2TTIeSvUspOvIFHNcvmoqNuFsItRPrYj3RvmS6aMr5cUJItayiu+Qg==","signatures":[{"sig":"MEQCIGWlB7MP0PJbulftHN7M1h4B+ttNeSY1fWs4zd3JpL2lAiAddvl4GDMddR+yyHiNitVtvlgoNBfgGPKcv3lCnwbKqA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":4710},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"ec357b561ec3393082a9958f06f4db1202078ecd","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"8.19.4","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"16.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.0.3_1746897222031_0.29419276061148647","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@cmike444/supply-and-demand-zones","version":"1.0.4","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.0.4","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"4faca28ffa556593b6624d52ab26bd6e90921e90","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.0.4.tgz","fileCount":49,"integrity":"sha512-2nAHp01QguPeCR+U+LD7dvQGP5ltZPJAHx8UmGb8e7cQPtkKp/0hZW/LljINqAdDZ6irKY7a3D350AS/p2g0XA==","signatures":[{"sig":"MEYCIQCuBOKQ9wRz8rxfZIfqZUJcw1pY1eXWbkD+P5XLXazxdgIhAPjDulN8Ge6Sgve8Ha/FSIOpgP4FuwiqH8DEAMuhEVEV","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":44865},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"1caf97ef95a399cf4bfd640b7a9474cf0d728549","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"8.19.4","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"16.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.0.4_1752848285752_0.05471788319601978","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@cmike444/supply-and-demand-zones","version":"1.0.6","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.0.6","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"cf61b24884b675bd03a8224d3a9527f386f11ecf","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.0.6.tgz","fileCount":49,"integrity":"sha512-t5exRyT8miSuyEaTMNM4jy62W6tt6L0imPzWhL6LdCuoTqVWcHMJhM4ke6aPF3SLHF8UpyrcFXkDiozVDhkF2w==","signatures":[{"sig":"MEQCIBaq5Az01CpV0MXELIzmbOYQN+kPbaetcTo3i8NFth+yAiBf0InPStTsps94+/OHlxeOp6tlcUpdsp2sNLAm3r/W9w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":44865},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"5ca6811f9e85f67caa292d8be7969d8b5cc06177","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"8.19.4","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"16.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.0.6_1752848705009_0.4732791017793381","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"@cmike444/supply-and-demand-zones","version":"1.0.7","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.0.7","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"bbb1365f8c0e1e40f938bef529366807d8e8b5dc","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.0.7.tgz","fileCount":49,"integrity":"sha512-MVJYbUMVqB4rqUa71oOXyrbHA9DjbTXCeDvMp3dIqI+A8/wiHgRwAaejQfZsBO0JiPhYOt3gCBvf5KST9SAAPg==","signatures":[{"sig":"MEYCIQDKv9huh3EA+nPp2//6/7NatgEsFvidLmhmayC9TYBolAIhAKMAbyPL7aCm4fwdet4KQsVFtyT0yDGDZmGSIMQ8FgsX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":44889},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"ddbf5c3eb1a157cac1639ee267a64181814a4679","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"9.5.1","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"18.14.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.0.7_1752848853510_0.16232314187043873","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"@cmike444/supply-and-demand-zones","version":"1.0.8","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.0.8","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"ea091d47289208f8c4e8b60fcebdb01ee10b549d","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.0.8.tgz","fileCount":49,"integrity":"sha512-5RVRJe20Yox88Wt608ZWpEaKV00vupWdwrOGwDojO86JYl6z1BoDu9nD1QHX3H9BlnmT7IGp+BjYMqp4DNVC+Q==","signatures":[{"sig":"MEUCIAzPa10GNgchBbsoIS0A3FyOrTOvPSHZhXsWbdmIsSycAiEAkqG68KIx3QLk4d7Y8dP4hmVIzSIilXVLqzdysRh1Udw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46877},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"5130c2e703a7eec21ca2fa070189f66d1ab63833","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"8.19.4","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"16.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.0.8_1752854651996_0.3291763137121593","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@cmike444/supply-and-demand-zones","version":"1.1.0","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.1.0","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"6ea9d6ac7a0a872506cd4ab88b8d5256e27902a6","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.1.0.tgz","fileCount":49,"integrity":"sha512-OW483kVI8WgQZ71x7vDvK9TVbe0SwrKBTUJqzXYRdxySAxCjYqmILrrdgmmeMglBB7Nz9j0/K0hArB+4k9zoIA==","signatures":[{"sig":"MEUCIFlRMG0ZhMUoEEMb6u0H8LHGZbNzdSH4gx3l7DUQBiJqAiEA3fEnt9FJqFu6rB8mUPrnhS3dADQeF6jv4D0GFidllkg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46331},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"a6ace83550b14fdf26be41ec1bea4885f357c750","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"11.11.1","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"25.8.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.1.0_1774501313643_0.9945124452479217","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@cmike444/supply-and-demand-zones","version":"1.2.0","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.2.0","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"f12b1a6b36963aed9579133957ea0853266072f1","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.2.0.tgz","fileCount":59,"integrity":"sha512-t/SZR59xfMpkHDJMUR14QCjNjHy4bRHqJLnCuFZ5E7MtcosFrkeBvrhtgppzVFbcF1eAsntH4iyFKdRYXy9pww==","signatures":[{"sig":"MEUCIQDSInA5J3nAFWxAhSlNk4hau5RZjpZJX3uKbEb4PLUzNAIgIIhtusW0P0vG1PECrXMLB1B2s6zcG+LhsCk9JVWoKpE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":90327},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"732edfe8325cf2feaf0242362f4ecb1ee4a8f8e6","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","fetch-candles":"npx ts-node scripts/fetch_candles.ts","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","visualize-tests":"npx ts-node scripts/visualizeTestCases.ts","visualize-zones":"npx ts-node scripts/visualizeZones.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"11.11.1","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"25.8.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14","@types/node":"^25.5.0","yahoo-finance2":"^3.14.0"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.2.0_1774930214920_0.33186704718392823","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@cmike444/supply-and-demand-zones","version":"1.2.1","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.2.1","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"35507efc052511524249283e45ee41662b50cd9c","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.2.1.tgz","fileCount":59,"integrity":"sha512-Ttxa9addfz3yUJguiyHTymbGHHBCiEutf7SKgZI3qnf8dpg4k2IPWHMJP2AzdkB40EyZW5CdXtcruaKeOg08lQ==","signatures":[{"sig":"MEUCIFFEBImgQ8TvPsjwjvS+f3Ip0pOU2b3AcUaAJ2xGtfJcAiEAiwTmf2xJrJB0tGlUxsKpFRAp+LUKgdbJgXDv4yOGOCY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91844},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"d57e4dd942fa367da08521be3f59087d857ae511","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","fetch-candles":"npx ts-node scripts/fetch_candles.ts","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","visualize-tests":"npx ts-node scripts/visualizeTestCases.ts","visualize-zones":"npx ts-node scripts/visualizeZones.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"11.11.1","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"25.8.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14","@types/node":"^25.5.0","yahoo-finance2":"^3.14.0"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.2.1_1774931186107_0.21104360106707487","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@cmike444/supply-and-demand-zones","version":"1.2.2","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.2.2","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"afd155d6574a038a6c4583d35b9a536aa51d90bc","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.2.2.tgz","fileCount":59,"integrity":"sha512-hCLQPP0jUBLIcKKGnvugmeg2Xl4jE2L2MM0S8ki2F4QKe4V86lV7mVuXvuGuHIPpkDDum4IQZi9M40sqH2Rw9w==","signatures":[{"sig":"MEQCIGJmghi6brnPu92kDcDgJPQW6sey/sy+dryT0d4jkWYwAiAT5cQnNWVAy/jUE2Ga1TOd/ZIhe4L58RfCajaF82bcqg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91004},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"cef96c92ded06ef360a0fb2ed58e5762dcbe8fe2","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","fetch-candles":"npx ts-node scripts/fetch_candles.ts","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","visualize-tests":"npx ts-node scripts/visualizeTestCases.ts","visualize-zones":"npx ts-node scripts/visualizeZones.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"11.11.1","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"25.8.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14","@types/node":"^25.5.0","yahoo-finance2":"^3.14.0"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.2.2_1774963777582_0.8198474007481504","host":"s3://npm-registry-packages-npm-production"}},"1.2.3":{"name":"@cmike444/supply-and-demand-zones","version":"1.2.3","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.2.3","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"2a3696da6298e6d78e09bf27f37a7feb352408c0","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.2.3.tgz","fileCount":59,"integrity":"sha512-TmhDa1O8YISr3XE+tS45SdDjV62yV6cx6GiWrK+NguCT9jSL1EOBZkf3DGI5bP82LhEh8qOQ2u913NVldEwMRg==","signatures":[{"sig":"MEYCIQCSAPqyxMfdUTDsQSW4kpo9k/kvQY+0m4nXhcEAiezcRAIhAL6Fi5fGs4lGz+Vw6PlCU5ojP7r2mCWvhKeRMAlW3+y8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91021},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"414d75935ea4d880c7385ba44afb80907199a059","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m 'Release v$npm_package_version' && git tag v$npm_package_version","fetch-candles":"npx ts-node scripts/fetch_candles.ts","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","visualize-tests":"npx ts-node scripts/visualizeTestCases.ts","visualize-zones":"npx ts-node scripts/visualizeZones.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"11.11.1","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"25.8.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14","@types/node":"^25.5.0","yahoo-finance2":"^3.14.0"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.2.3_1774963890738_0.3164884941851007","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@cmike444/supply-and-demand-zones","version":"1.3.0","keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","_id":"@cmike444/supply-and-demand-zones@1.3.0","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"dist":{"shasum":"063623155b06be27fd4a3d8818bf4dc0bae1bae2","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.3.0.tgz","fileCount":59,"integrity":"sha512-RF64ywVz9qba4ElIR0dV1BG3R1ACyJuYGAS867tCxnNS97l6pwXp/pqCl1/ASs5CPYzFLuu66S/Hsz9X8Vlkwg==","signatures":[{"sig":"MEUCIEDA4P5kXiG3Tdg7rhUGDL9TNFX1/cFS9HSrmxCsV/aXAiEAhU74tIR5w2sZYbEDL8UZGdstSrgPCN3ZLBdg35Ul7UM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":95941},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"60741a727248059ba5e619d40444f472fae4a044","private":false,"scripts":{"test":"jest","build":"tsc","version":"git add . && git commit -m \"Release v$npm_package_version\" && git tag v$npm_package_version && git push --follow-tags && gh release create v$npm_package_version --title \"v$npm_package_version\" --generate-notes","fetch-candles":"npx ts-node scripts/fetch_candles.ts","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","visualize-tests":"npx ts-node scripts/visualizeTestCases.ts","visualize-zones":"npx ts-node scripts/visualizeZones.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts"},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"repository":{"url":"git+https://github.com/cmike444/SupplyAndDemand.git","type":"git"},"_npmVersion":"11.11.1","description":"A library for identifying supply and demand zones in candlestick data.","directories":{},"_nodeVersion":"25.8.2","dependencies":{"hf-types":"github:cmike444/hf-types"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","@types/jest":"^29.5.14","@types/node":"^25.5.0","yahoo-finance2":"^3.14.0"},"_npmOperationalInternal":{"tmp":"tmp/supply-and-demand-zones_1.3.0_1775455898612_0.8305309255260287","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@cmike444/supply-and-demand-zones","version":"1.3.1","description":"A library for identifying supply and demand zones in candlestick data.","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","test":"jest","identify-zones":"ts-node scripts/identifyZonesFromFile.ts","convert-to-candle":"ts-node scripts/convertToCandle.ts","fetch-candles":"npx ts-node scripts/fetch_candles.ts","visualize-zones":"npx ts-node scripts/visualizeZones.ts","visualize-tests":"npx ts-node scripts/visualizeTestCases.ts","version":"git add . && git commit -m \"Release v$npm_package_version\" && git tag v$npm_package_version && git push --follow-tags && gh release create v$npm_package_version --title \"v$npm_package_version\" --generate-notes"},"keywords":["supply","demand","zones","candlestick","trading"],"author":{"name":"Christopher Mikelson"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/cmike444/SupplyAndDemand.git"},"private":false,"dependencies":{"hf-types":"github:cmike444/hf-types"},"devDependencies":{"@types/jest":"^29.5.14","@types/node":"^25.5.0","jest":"^29.7.0","ts-jest":"^29.3.2","typescript":"^5.0.0","yahoo-finance2":"^3.14.0"},"gitHead":"055ebebdea7b99ea41c1cbe78c5b958b3ec829fb","_id":"@cmike444/supply-and-demand-zones@1.3.1","bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"homepage":"https://github.com/cmike444/SupplyAndDemand#readme","_nodeVersion":"25.8.2","_npmVersion":"11.11.1","dist":{"integrity":"sha512-29TgF8zL0HKozTX9Dg41ye3Nt+mmTArHs9UebLv9QAP+ykRof47klhGHBzwd7UaE85zvGhF0rOXCQ0cuN+TuZA==","shasum":"cd6998f3d17d4291f45819819e94e2edafd9ffa4","tarball":"https://registry.npmjs.org/@cmike444/supply-and-demand-zones/-/supply-and-demand-zones-1.3.1.tgz","fileCount":59,"unpackedSize":95937,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDCNAzL8Gl1TLJ27uxeX/Jf1b6XI8qIYlOAy21hU6cK9gIgfq7OmcYZqbvebyZq7gRQcn7CDaPv9Ywx4KVUEC2n6nU="}]},"_npmUser":{"name":"cmike444","email":"chrismikelson@gmail.com"},"directories":{},"maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/supply-and-demand-zones_1.3.1_1778127755164_0.16875032358408393"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-03T18:39:14.013Z","modified":"2026-05-07T04:22:35.439Z","1.0.0":"2025-05-03T18:39:14.314Z","1.0.2":"2025-05-04T17:29:57.850Z","1.0.3":"2025-05-10T17:13:42.218Z","1.0.4":"2025-07-18T14:18:05.946Z","1.0.6":"2025-07-18T14:25:05.181Z","1.0.7":"2025-07-18T14:27:33.691Z","1.0.8":"2025-07-18T16:04:12.172Z","1.1.0":"2026-03-26T05:01:53.838Z","1.2.0":"2026-03-31T04:10:15.058Z","1.2.1":"2026-03-31T04:26:26.267Z","1.2.2":"2026-03-31T13:29:37.742Z","1.2.3":"2026-03-31T13:31:30.885Z","1.3.0":"2026-04-06T06:11:38.795Z","1.3.1":"2026-05-07T04:22:35.306Z"},"bugs":{"url":"https://github.com/cmike444/SupplyAndDemand/issues"},"author":{"name":"Christopher Mikelson"},"license":"MIT","homepage":"https://github.com/cmike444/SupplyAndDemand#readme","keywords":["supply","demand","zones","candlestick","trading"],"repository":{"type":"git","url":"git+https://github.com/cmike444/SupplyAndDemand.git"},"description":"A library for identifying supply and demand zones in candlestick data.","maintainers":[{"name":"cmike444","email":"chrismikelson@gmail.com"}],"readme":"# Supply and Demand Zones\n\nA TypeScript library for identifying supply and demand zones in candlestick data, designed for financial and trading applications.\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Confidence Model](#confidence-model)\n- [API Reference](#api-reference)\n  - [Zone Detection](#zone-detection)\n  - [Candle Utilities](#candle-utilities)\n  - [Advanced / Internal](#advanced--internal)\n- [Types](#types)\n- [Enums](#enums)\n- [Constants](#constants)\n- [Developer Tools](#developer-tools)\n  - [Gathering Datasets](#gathering-datasets)\n  - [Visualizing Zones](#visualizing-zones)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n\n- Detect **supply zones** (Rally-Base-Drop, Drop-Base-Drop patterns)\n- Detect **demand zones** (Drop-Base-Rally, Rally-Base-Rally patterns)\n- **Confidence scoring** (0–1) on every zone, derived from departure strength, volume, position, freshness, and timeframe\n- **Freshness filtering** via `filterFreshZones` — removes stale zones whose price levels conflict with newer zones\n- Candle utility functions for body size, range, bullish/bearish, decisive, indecisive, and explosive detection\n- Full TypeScript types, enums, and constants\n\n## Installation\n\n```sh\nnpm install supply-and-demand-zones\n```\n\n## Quick Start\n\n### Importing\n\n```typescript\nimport {\n  identifyZones,\n  filterFreshZones,\n  candleBody,\n  isBullishCandle,\n  ZONE_TYPE,\n  ZONE_DIRECTION,\n  DEFAULT_DECISIVE_THRESHOLD,\n} from 'supply-and-demand-zones';\n```\n\n### Identify Supply and Demand Zones\n\n```typescript\nimport { identifyZones } from 'supply-and-demand-zones';\n\nconst candles = [\n  { timestamp: 1, open: 100, high: 110, low: 95, close: 105 },\n  { timestamp: 2, open: 105, high: 115, low: 100, close: 110 },\n  { timestamp: 3, open: 110, high: 120, low: 105, close: 115 },\n];\n\nconst { supplyZones, demandZones } = identifyZones(candles);\n\nconsole.log('Supply Zones:', supplyZones);\nconsole.log('Demand Zones:', demandZones);\n```\n\n### Filter Fresh Zones\n\nRemove stale zones whose price levels conflict with newer ones:\n\n```typescript\nimport { identifyZones, filterFreshZones } from 'supply-and-demand-zones';\n\nconst { supplyZones, demandZones } = identifyZones(candles);\nconst fresh = filterFreshZones(supplyZones, demandZones);\n\nconsole.log('Fresh Supply Zones:', fresh.supplyZones);\nconsole.log('Fresh Demand Zones:', fresh.demandZones);\n```\n\nFilter by confidence score:\n\n```typescript\nconst strongZones = fresh.demandZones.filter(z => z.confidence >= 0.7);\n```\n\n### Utility Functions\n\n**Candle body size:**\n\n```typescript\nimport { candleBody } from 'supply-and-demand-zones';\n\nconst candle = { timestamp: 1, open: 100, high: 110, low: 95, close: 105 };\nconsole.log(candleBody(candle)); // 5\n```\n\n**Bullish / bearish check:**\n\n```typescript\nimport { isBullishCandle } from 'supply-and-demand-zones';\n\nconsole.log(isBullishCandle(candle)); // true\n```\n\n**Decisive check:**\n\n```typescript\nimport { isDecisiveCandle } from 'supply-and-demand-zones';\n\nconsole.log(isDecisiveCandle(candle)); // true if body/range >= 0.5\n```\n\n**Explosive (Extended Range Candle) check:**\n\n```typescript\nimport { isExplosiveCandle } from 'supply-and-demand-zones';\n\nconst candle = { timestamp: 1, open: 100, high: 150, low: 95, close: 145 };\n\n// Basic — body/range ratio >= 0.70\nconsole.log(isExplosiveCandle(candle)); // true\n\n// With ATR magnitude check — range must also be >= 1.5 × ATR (e.g. 30)\nconsole.log(isExplosiveCandle(candle, 0.70, 30)); // true if range >= 30\n```\n\n**Enums:**\n\n```typescript\nimport { ZONE_DIRECTION, DEFAULT_DECISIVE_THRESHOLD } from 'supply-and-demand-zones';\n\nconsole.log(ZONE_DIRECTION.SUPPLY);       // 0\nconsole.log(ZONE_DIRECTION.DEMAND);       // 1\nconsole.log(DEFAULT_DECISIVE_THRESHOLD);  // 0.5\n```\n\n## Confidence Model\n\nEvery zone returned by `identifyZones` carries a `confidence` score in [0, 1].\n\n### Departure Sub-score (factors 1–4)\n\nEvaluates the strength of the leg that left the zone:\n\n| Factor | Description |\n|---|---|\n| **countFactor** | Proportion of departure candles that are decisive or explosive in the departure direction. |\n| **rangeFactor** | Average departure candle range normalised by local ATR, clamped to [0, 1]. Falls back to `0.5` when ATR is zero. |\n| **volumeFactor** | Departure vs. base volume ratio mapped through `ratio / (ratio + 1)`. Falls back to `0.5` when volume is absent. |\n| **timeFactor** | \"Time at Level\": 1–3 base candles → `1.0` (tight imbalance); 4–6 candles → `0.5`; more → `0`. |\n\n```\ndepartureScore = (countFactor + rangeFactor + volumeFactor + timeFactor) / 4\n```\n\n### Full Zone Score (factors 5–7)\n\nThree additional context factors are blended in when scoring through `identifyZones`:\n\n| Factor | Description |\n|---|---|\n| **positionFactor** | Price position within the chart's full range; higher for supply zones at elevated prices and demand zones at depressed prices. |\n| **freshnessFactor** | `1.0` if price never re-entered the zone; `0.5` if price touched the proximal line but was repelled before breaching the distal line. |\n| **timeframeFactor** | Log-normalised median candle interval from 1 minute (`0.0`) to 1 week (`1.0`); higher timeframe zones carry more institutional weight. |\n\n```\nconfidence = (departureScore × 4 + positionFactor + freshnessFactor + timeframeFactor) / 7\n```\n\n## API Reference\n\n### Zone Detection\n\n---\n\n#### `identifyZones(candles: Candle[]): { supplyZones: SupplyZone[], demandZones: DemandZone[] }`\n\nScans an array of candlestick data and returns all detected supply and demand zones, each with a `confidence` score computed using the full 7-factor model. See [Confidence Model](#confidence-model) for details.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `candles` | `Candle[]` | Array of candlestick data to scan. |\n\n**Returns:** `{ supplyZones: SupplyZone[], demandZones: DemandZone[] }`\n\n---\n\n#### `filterFreshZones(supplyZones: SupplyZone[], demandZones: DemandZone[]): { supplyZones: SupplyZone[], demandZones: DemandZone[] }`\n\nFilters out stale zones whose price levels conflict with newer zones. A demand zone's proximal line (upper edge) must never be above a supply zone's proximal line (lower edge). When a conflict is found, the zone with the older `endTimestamp` is removed. On a tie, the demand zone is removed.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `supplyZones` | `SupplyZone[]` | Supply zones to filter. |\n| `demandZones` | `DemandZone[]` | Demand zones to filter. |\n\n**Returns:** `{ supplyZones: SupplyZone[], demandZones: DemandZone[] }` — only non-conflicting zones.\n\n---\n\n#### `rallyBaseDrop(candles: Candle[], localATR?: number): SupplyZone | null`\n\nDetects a Rally-Base-Drop supply zone pattern.\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candles` | `Candle[]` | — | Array starting at the first candle of the potential pattern. |\n| `localATR` | `number` | `0` | ATR for base validation. |\n\n**Returns:** A `SupplyZone` if the pattern is detected, `null` otherwise.\n\n---\n\n#### `dropBaseDrop(candles: Candle[], localATR?: number): SupplyZone | null`\n\nDetects a Drop-Base-Drop supply zone pattern.\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candles` | `Candle[]` | — | Array starting at the first candle of the potential pattern. |\n| `localATR` | `number` | `0` | ATR for base validation. |\n\n**Returns:** A `SupplyZone` if the pattern is detected, `null` otherwise.\n\n---\n\n#### `dropBaseRally(candles: Candle[], localATR?: number): DemandZone | null`\n\nDetects a Drop-Base-Rally demand zone pattern.\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candles` | `Candle[]` | — | Array starting at the first candle of the potential pattern. |\n| `localATR` | `number` | `0` | ATR for base validation. |\n\n**Returns:** A `DemandZone` if the pattern is detected, `null` otherwise.\n\n---\n\n#### `rallyBaseRally(candles: Candle[], localATR?: number): DemandZone | null`\n\nDetects a Rally-Base-Rally demand zone pattern.\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candles` | `Candle[]` | — | Array starting at the first candle of the potential pattern. |\n| `localATR` | `number` | `0` | ATR for base validation. |\n\n**Returns:** A `DemandZone` if the pattern is detected, `null` otherwise.\n\n---\n\n### Candle Utilities\n\n---\n\n#### `candleBody(candle: Candle): number`\n\n| Parameter | Type | Description |\n|---|---|---|\n| `candle` | `Candle` | The candlestick to measure. |\n\n**Returns:** `|close - open|`\n\n---\n\n#### `candleRange(candle: Candle): number`\n\n| Parameter | Type | Description |\n|---|---|---|\n| `candle` | `Candle` | The candlestick to measure. |\n\n**Returns:** `high - low`\n\n---\n\n#### `isBullishCandle(candle: Candle): boolean`\n\n**Returns:** `true` if `close > open`.\n\n---\n\n#### `isBearishCandle(candle: Candle): boolean`\n\n**Returns:** `true` if `close < open`.\n\n---\n\n#### `isDecisiveCandle(candle: Candle, threshold?: number): boolean`\n\nDetermines if a candle has a large body relative to its range.\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candle` | `Candle` | — | The candlestick to evaluate. |\n| `threshold` | `number` | `0.5` | Minimum body-to-range ratio. |\n\n**Returns:** `true` if body-to-range ratio ≥ `threshold`.\n\n---\n\n#### `isIndecisiveCandle(candle: Candle, threshold?: number): boolean`\n\nDetermines if a candle has a small body relative to its range.\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candle` | `Candle` | — | The candlestick to evaluate. |\n| `threshold` | `number` | `0.5` | Maximum body-to-range ratio. |\n\n**Returns:** `true` if body-to-range ratio is strictly below `threshold`.\n\n---\n\n#### `isExplosiveCandle(candle: Candle, threshold?: number, minATR?: number): boolean`\n\nDetermines if a candle is an Extended Range Candle (ERC) — the \"leg-out\" that signals an institutional imbalance.\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candle` | `Candle` | — | The candlestick to evaluate. |\n| `threshold` | `number` | `0.70` | Minimum body-to-range ratio. |\n| `minATR` | `number` | `0` | Minimum required total range. When > 0, candles whose `high − low` falls below this value are rejected even if their body ratio qualifies. Typically passed as `MIN_EXPLOSIVE_ATR_MULTIPLIER × localATR` (1.5× ATR). |\n\n**Returns:** `true` if body-to-range ratio ≥ `threshold` **and** `high − low` ≥ `minATR`.\n\n---\n\n#### `isBullishDecisiveCandle(candle: Candle, threshold?: number): boolean`\n\n**Returns:** `true` if the candle is bullish and body-to-range ratio ≥ `threshold` (default `0.5`).\n\n---\n\n#### `isBearishDecisiveCandle(candle: Candle, threshold?: number): boolean`\n\n**Returns:** `true` if the candle is bearish and body-to-range ratio ≥ `threshold` (default `0.5`).\n\n---\n\n#### `isBullishExplosiveCandle(candle: Candle, threshold?: number): boolean`\n\n**Returns:** `true` if the candle is bullish and body-to-range ratio ≥ `threshold` (default `0.70`).\n\n---\n\n#### `isBearishExplosiveCandle(candle: Candle, threshold?: number): boolean`\n\n**Returns:** `true` if the candle is bearish and body-to-range ratio ≥ `threshold` (default `0.70`).\n\n---\n\n#### `atr(candles: Candle[], period?: number): number`\n\nComputes the Average True Range using a simple mean over the last `period` true-range values. True Range is `max(high − low, |high − prevClose|, |low − prevClose|)`. For the first candle (no previous close), TR = `high − low`. Returns `0` for an empty array.\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candles` | `Candle[]` | — | Array of candles representing the context window. |\n| `period` | `number` | `14` | Look-back period. |\n\n**Returns:** Mean TR over the last `period` values, or `0` if the array is empty.\n\n---\n\n### Advanced / Internal\n\nThese functions are exported for advanced use cases. They are called internally by the pattern detectors.\n\n---\n\n#### `calculateConfidence(departureCandles: Candle[], baseCandles: Candle[], localATR: number, isUpwardDeparture: boolean): number`\n\nCalculates the **departure sub-score** (factors 1–4 of the full confidence model). When called through `identifyZones`, three additional context factors are blended in automatically. See [Confidence Model](#confidence-model).\n\n| Parameter | Type | Description |\n|---|---|---|\n| `departureCandles` | `Candle[]` | Candles forming the explosive leg away from the zone. |\n| `baseCandles` | `Candle[]` | Candles forming the indecisive base of the zone. |\n| `localATR` | `number` | ATR for the context window around the zone. |\n| `isUpwardDeparture` | `boolean` | `true` for a bullish departure (demand zone), `false` for bearish (supply zone). |\n\n**Returns:** Departure sub-score in [0, 1].\n\n---\n\n#### `isValidBase(baseCandles: Candle[], precedingCandle: Candle, localATR: number): boolean`\n\nValidates that a base sequence is well-formed relative to local volatility. Applies two checks:\n\n1. **Gap check** — rejects if any consecutive open-to-prior-close gap within `[precedingCandle, ...baseCandles]` exceeds `MAX_BASE_GAP_ATR_MULTIPLIER × localATR`.\n2. **Height check** — rejects if the base's full high-to-low range exceeds `MAX_ZONE_ATR_MULTIPLIER × localATR`.\n\nReturns `true` unconditionally when `localATR ≤ 0`.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `baseCandles` | `Candle[]` | The indecisive candles forming the base. |\n| `precedingCandle` | `Candle` | The candle immediately before the base. |\n| `localATR` | `number` | ATR for the context window around the base. |\n\n**Returns:** `true` if the base passes both checks, `false` otherwise.\n\n---\n\n#### `findPatternEnd(candles: Candle[], startIndex: number, condition: (candle: Candle) => boolean, maxCount?: number): number`\n\nAdvances through `candles` from `startIndex` while `condition` holds, returning the index of the first candle that does not satisfy the condition (or the end of the array).\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `candles` | `Candle[]` | — | Array of candles. |\n| `startIndex` | `number` | — | Index to start scanning from. |\n| `condition` | `(c: Candle) => boolean` | — | Predicate applied to each candle. |\n| `maxCount` | `number` | — | Maximum number of candles to advance. |\n\n**Returns:** Index of the first non-matching candle, or `candles.length` if all checked candles match.\n\n---\n\n## Types\n\n### `Candle`\n\nRepresents a single candlestick.\n\n| Property | Type | Required | Description |\n|---|---|---|---|\n| `timestamp` | `number` | Yes | Time of the candlestick. |\n| `open` | `number` | Yes | Opening price. |\n| `high` | `number` | Yes | Highest price. |\n| `low` | `number` | Yes | Lowest price. |\n| `close` | `number` | Yes | Closing price. |\n| `volume` | `number` | No | Trading volume. Used in confidence scoring when present. |\n\n### `Zone`\n\nBase interface for all zones.\n\n| Property | Type | Description |\n|---|---|---|\n| `proximalLine` | `number` | Near edge of the zone (closest to current price). Derived from candle **bodies** only — for supply zones: the lowest body (open/close) across the base; for demand zones: the highest body (open/close) across the base. |\n| `distalLine` | `number` | Far edge of the zone. Spans the **entire formation** (leg-in + base + leg-out) using full wicks — for supply zones: the highest `high`; for demand zones: the lowest `low`. |\n| `startTimestamp` | `number` | Timestamp of the first candle in the pattern. |\n| `endTimestamp` | `number` | Timestamp of the last candle in the pattern. |\n| `confidence` | `number` | Score in [0, 1] indicating zone strength. Blends 7 equally-weighted factors: departure quality (×3), position, freshness, timeframe, and `rrScore`. |\n| `rrScore` | `number` | Departure-based risk/reward score in [0, 1]. `min(departureExtent / zoneWidth / 5, 1)` — a score of 1.0 represents ≥ 5:1 R:R. Always set by `identifyZones`. |\n| `entryPrice` | `number` | Suggested limit order entry price. Equal to `proximalLine`. Always set by `identifyZones`. |\n| `stopPrice` | `number` | Hard stop price — zone invalidation level. Equal to `distalLine`. Always set by `identifyZones`. |\n| `targetPrice` | `number \\| null` | Profit target — proximal line of the nearest opposing zone. `null` when no opposing zone exists in the dataset. Always set by `identifyZones`. |\n\n### `SupplyZone`\n\nExtends `Zone`. Represents a supply zone.\n\n| Property | Type | Description |\n|---|---|---|\n| `direction` | `ZONE_DIRECTION` | Always `ZONE_DIRECTION.SUPPLY`. |\n| `type` | `ZONE_TYPE` | `ZONE_TYPE.RALLY_BASE_DROP` or `ZONE_TYPE.DROP_BASE_DROP`. |\n\n### `DemandZone`\n\nExtends `Zone`. Represents a demand zone.\n\n| Property | Type | Description |\n|---|---|---|\n| `direction` | `ZONE_DIRECTION` | Always `ZONE_DIRECTION.DEMAND`. |\n| `type` | `ZONE_TYPE` | `ZONE_TYPE.DROP_BASE_RALLY` or `ZONE_TYPE.RALLY_BASE_RALLY`. |\n\n## Enums\n\n### `ZONE_DIRECTION`\n\n| Value | Name | Description |\n|---|---|---|\n| `0` | `SUPPLY` | A supply zone — price is expected to fall from here. |\n| `1` | `DEMAND` | A demand zone — price is expected to rise from here. |\n\n### `ZONE_TYPE`\n\n| Value | Name |\n|---|---|\n| `0` | `DROP_BASE_DROP` |\n| `1` | `RALLY_BASE_RALLY` |\n| `2` | `DROP_BASE_RALLY` |\n| `3` | `RALLY_BASE_DROP` |\n\n## Constants\n\n| Constant | Value | Description |\n|---|---|---|\n| `DEFAULT_DECISIVE_THRESHOLD` | `0.5` | Minimum body-to-range ratio for a decisive candle. |\n| `DEFAULT_EXPLOSIVE_THRESHOLD` | `0.7` | Minimum body-to-range ratio for an explosive candle (ERC). |\n| `DEFAULT_ATR_PERIOD` | `14` | Look-back period for ATR calculation (Wilder's standard). |\n| `MIN_RALLY_CANDLES` | `2` | Minimum consecutive bullish candles required to define a rally leg. |\n| `MIN_DROP_CANDLES` | `2` | Minimum consecutive bearish candles required to define a drop leg. |\n| `MIN_BASE_CANDLES` | `1` | Minimum indecisive candles required for a valid base. |\n| `MAX_BASE_CANDLES` | `6` | Maximum indecisive candles allowed in a base. More than 6 indicates the imbalance is too dispersed. |\n| `MIN_EXPLOSIVE_ATR_MULTIPLIER` | `1.5` | Minimum ERC total range as a multiple of ATR. The leg-out must be significantly larger than surrounding price action. |\n| `MAX_ZONE_ATR_MULTIPLIER` | `1.5` | Maximum base high-to-low range as a multiple of ATR. |\n| `MAX_BASE_GAP_ATR_MULTIPLIER` | `0.5` | Maximum open-to-prior-close gap within a base as a multiple of ATR. |\n\n## Developer Tools\n\n### Gathering Datasets\n\nThe `scripts/fetch_candles.ts` script downloads OHLCV candlestick data for any ticker via [yahoo-finance2](https://www.npmjs.com/package/yahoo-finance2) and saves it as a JSON file in the `data/` folder. The filename is automatically generated from the symbol, interval, and actual date range of the data.\n\n#### Prerequisites\n\n```sh\nnpm install\n```\n\n#### Usage\n\n```sh\nnpm run fetch-candles <SYMBOL> [INTERVAL] [PERIOD]\n```\n\n| Argument | Required | Default | Description |\n|---|---|---|---|\n| `SYMBOL` | Yes | — | Ticker symbol (e.g. `SPY`, `AAPL`, `IBIT`) |\n| `INTERVAL` | No | `1m` | Bar size: `1m`, `2m`, `5m`, `15m`, `30m`, `60m`, `1d` |\n| `PERIOD` | No | `7d` | Lookback window: `1d`, `5d`, `7d`, `1mo`, `3mo`, `6mo`, `1y` |\n\n#### Examples\n\n```sh\n# 1-minute SPY data for the last 7 days (default)\nnpm run fetch-candles SPY\n\n# 5-minute AAPL data for the last 60 days\nnpm run fetch-candles AAPL 5m 3mo\n\n# Daily IBIT data for the last year\nnpm run fetch-candles IBIT 1d 1y\n```\n\n#### Output\n\nFiles are saved to `data/` with the naming convention `<SYMBOL>_<INTERVAL>_<STARTDATE>_<ENDDATE>.json`:\n\n```\ndata/SPY_1m_20260319_20260327.json\ndata/AAPL_5m_20251231_20260327.json\ndata/IBIT_1d_20250329_20260327.json\n```\n\nEach candle object contains:\n\n```json\n{\n  \"timestamp\": 1773927000000,\n  \"open\": 656.97,\n  \"high\": 657.00,\n  \"low\": 655.17,\n  \"close\": 655.85,\n  \"volume\": 5070007\n}\n```\n\n#### Interval Limits\n\n| Interval | Max Lookback |\n|---|---|\n| `1m` | 7 days |\n| `2m`, `5m`, `15m`, `30m` | 60 days |\n| `60m` | 730 days |\n| `1d` and above | Unlimited |\n\n### Visualizing Zones\n\nTwo scripts generate self-contained HTML files that can be opened in any browser.\n\n#### `npm run visualize-zones`\n\nRenders identified zones on an interactive candlestick chart powered by [Apache ECharts 5](https://echarts.apache.org/).\n\n```sh\nnpm run visualize-zones -- <path/to/data.json> [output.html]\n```\n\nIf no output path is given, the file is auto-named `<input-basename>_zones.html` and written to the `example/` directory (gitignored).\n\n**Chart features:**\n- Dark-theme ECharts 5 candlestick chart\n- Gap-free x-axis — timestamps are mapped to sequential indices, eliminating overnight and weekend gaps\n- Optional volume panel rendered below the price chart when candle data contains a `volume` field\n- Scroll, pan, and zoom via mouse wheel or the slider below the chart; defaults to the last ~500 candles\n- Only **intact** zones are displayed:\n  - Stale zones (price-level conflicts between supply and demand) are removed via `filterFreshZones`\n  - Breached zones (price fully wicked through the distal line after the zone formed) are additionally removed\n- **Zone fill opacity** scales with `confidence` — faint at 0, solid at 1\n- **Proximal and distal rays** extend from the zone's end timestamp to the right edge of the chart\n- Each proximal ray is labeled with the price level, a **letter grade** (A+ through F), and the numeric score\n- The subtitle bar shows total zones identified, the fresh count, and how many stale/breached zones were removed\n\n#### `npm run visualize-tests`\n\nGenerates `example/testCases.html` — an interactive chart that plots the candle fixtures used in the test suite alongside their detected zones. Useful for visually verifying pattern detection logic.\n\n```sh\nnpm run visualize-tests\n```\n\n## Contributing\n\nContributions are welcome! If you have ideas for improvements or new features, feel free to open an issue or submit a pull request.\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.","readmeFilename":"README.md"}