আমি প্রায়ই ইনভেন্টর প্ল্যাটফর্মে আড্ডা দেই এবং সবসময় গুপ্তধন খুঁজে পাই। আজ আমি ২১ বছর বয়সী এক যুবককে খুঁজে পেয়েছিপ্রবণতা কৌশল, আমি মূল লেখকের সূক্ষ্ম এবং নিখুঁত কোড কাঠামোর প্রশংসা করি, এবং এর উচ্চ নমনীয়তা রয়েছে। মূল কৌশলটি হল JS সংস্করণ, যা পাইথন বন্ধুদের সুবিধার জন্য পুনর্লিখন করা হয়েছে।
সত্যি বলতে, অনেক নতুন ট্রেডারই প্রথম কোয়ান্টিটেটিভ ট্রেডিংয়ে নামার সময় অনেক পথ পাড়ি দেন। তারা প্রায়শই ব্যর্থ অর্ডার, দুর্বল ঝুঁকি ব্যবস্থাপনার কারণে লোকসান এবং কৌশল পুনরায় চালু করার পরে ডেটা হারানোর মতো সমস্যার সম্মুখীন হন। পরে, আমি ধীরে ধীরে একটি ভালো কাঠামোর গুরুত্ব বুঝতে পেরেছি, যা আমাদের অনেক বিপদ এড়াতে সাহায্য করতে পারে। এই ট্রেন্ড স্ট্র্যাটেজি ফ্রেমওয়ার্কটি একটি মূল্যবান হাতিয়ার। এটি কেবল একটি সাধারণ ট্রেডিং কৌশলের চেয়েও বেশি কিছু; এটি একটি টুলবক্সের মতো, যা আপনাকে অর্ডার প্লেসমেন্ট, স্টপ-লস অর্ডার এবং ডেটা ম্যানেজমেন্টের মতো মৌলিক কিন্তু গুরুত্বপূর্ণ ফাংশন প্রদান করে। আপনাকে কেবল "কখন কিনবেন" এবং "কখন বিক্রি করবেন" এই মূল প্রশ্নগুলিতে মনোনিবেশ করতে হবে। তদুপরি, কাঠামোটি খুবই উন্মুক্ত, যা আপনাকে সহজেই MACD, RSI, অথবা আপনার পছন্দের অন্য যেকোনো সূচকের জন্য EMA অদলবদল করতে দেয়। ট্রেন্ড অনুসরণ করতে চান? কোন সমস্যা নেই। গড় রিভার্সন চেষ্টা করতে চান? এমনকি একাধিক সূচক একত্রিত করতে চান? অবশ্যই। এই নমনীয়তা অবিশ্বাস্যভাবে কার্যকর; আপনি বিভিন্ন ধারণা নিয়ে পরীক্ষা করার জন্য একই কোড পরিবর্তন করতে পারেন।
আমি আজ এই কাঠামোটি শেয়ার করছি, আশা করি এটি পরিমাণগত বিনিয়োগ অন্বেষণকারীদের জন্য সহায়ক হবে। নীচে এই কাঠামোর প্রতিটি উপাদানের একটি বিস্তারিত ভূমিকা দেওয়া হল, যা আপনার জন্য কার্যকর হবে বলে আমি বিশ্বাস করি।
কাঠামোর গঠন এবং কার্যকারিতা
মাল্টি-কমোডিটি ট্রেডিং ফ্রেমওয়ার্কে ব্যবহৃত একাধিক স্বাধীন ফাংশনের তুলনায়, এই ফ্রেমওয়ার্কটি একটি ক্লাস ফর্ম্যাট ব্যবহার করে একটি কৌশলের বিভিন্ন অংশকে সংগঠিত এবং পরিচালনা করার চেষ্টা করে। এই অবজেক্ট-ওরিয়েন্টেড ডিজাইনটি কেবল কোড রক্ষণাবেক্ষণ এবং স্কেলেবিলিটি উন্নত করে না, বরং কৌশলগত উপাদানগুলিকে আরও মডুলার করে তোলে, পরবর্তী সমন্বয় এবং অপ্টিমাইজেশনকে সহজতর করে। ফ্রেমওয়ার্কটিতে মূলত নিম্নলিখিত বিভাগগুলি রয়েছে, প্রতিটির নিজস্ব নির্দিষ্ট ফাংশন রয়েছে, যা কৌশলটির নমনীয়তা এবং ব্যবহারিকতা নিশ্চিত করে।
আরম্ভ এবং সেটআপ
init ফাংশন
- কার্যকারিতা:
__init__এই ফাংশনটি কৌশল শ্রেণীর প্রাথমিককরণ পদ্ধতি, যা কৌশলের মৌলিক কনফিগারেশন সেট করার, ভেরিয়েবল শুরু করার এবং বাজারের তথ্য প্রাপ্তির জন্য দায়ী। এই ফাংশনটি নিশ্চিত করে যে কৌশলটি চালানোর আগে প্রয়োজনীয় পরামিতিগুলি কনফিগার করা হয়েছে, যাতে পরবর্তী ট্রেডিং কার্যক্রমগুলি সুচারুভাবে সম্পাদন করা যায়। - পদক্ষেপ:
- মৌলিক কনফিগারেশন: ট্রেডিং মুদ্রা, চুক্তির ধরণ, লাভ-লাভ এবং স্টপ-লস নিয়ম ইত্যাদি সেট করুন।
- বাজারের তথ্য:অর্ডারের বৈধতা নিশ্চিত করতে চুক্তির মূল্য নির্ভুলতা এবং পরিমাণ নির্ভুলতা অর্জন করুন।
- ভেরিয়েবল শুরু করা হচ্ছে: বাজারের অবস্থার উপর ভিত্তি করে কৌশলগুলিকে সিদ্ধান্ত নিতে সহায়তা করার জন্য ট্রেন্ড জাজমেন্ট, স্টপ-প্রফিট এবং স্টপ-লস প্যারামিটার, পরিসংখ্যানগত পরিবর্তনশীল ইত্যাদি অন্তর্ভুক্ত।
- এক্সচেঞ্জ সেটিংস: বাজারের তথ্য অনুসারে এক্সচেঞ্জ API ইন্টারফেস কনফিগার করুন, যেমন মার্জিন নির্ধারণ, নির্ভুলতা ইত্যাদি।
initDatas ফাংশন
- কার্যকারিতা: কৌশলটি চলমান থাকাকালীন ডেটা শুরু করে, যার মধ্যে অ্যাকাউন্ট সম্পদ, লাভের পরিসংখ্যান ইত্যাদি অন্তর্ভুক্ত।
- পদক্ষেপ:
- নীতি বাস্তবায়নের সময় বাঁচান।
- স্থানীয় ব্যবহারকারীর তথ্য পড়ুন।
- অ্যাকাউন্টের সম্পদ, আয়ের পরিসংখ্যান এবং অন্যান্য তথ্য শুরু করুন।
- টেক প্রফিট এবং কলব্যাক টেক প্রফিট একই সময়ে সক্রিয় আছে কিনা তা পরীক্ষা করে।
ডেটা ব্যবস্থাপনা এবং সঞ্চয়স্থান
saveStrategyRunTime ফাংশন
- কার্যকারিতা: পরবর্তী পরিসংখ্যান এবং পর্যবেক্ষণের জন্য নীতির শুরুর সময় সংরক্ষণ করুন।
- পদক্ষেপ:
- চলমান সময় স্থানীয়ভাবে সংরক্ষণ করা হয়েছে কিনা তা পরীক্ষা করুন।
- যদি সংরক্ষণ না করা থাকে, তাহলে বর্তমান সময় রেকর্ড করুন এবং স্থানীয়ভাবে সংরক্ষণ করুন।
- যদি এটি সংরক্ষণ করা হয়ে থাকে, তাহলে স্থানীয়ভাবে সংরক্ষিত সময়টি পড়ুন।
setStrategyRunTime ফাংশন
- কার্যকারিতা: নীতির শুরুর সময় নির্ধারণ করুন এবং এটি স্থানীয় স্টোরেজে সংরক্ষণ করুন।
- পদক্ষেপ:
- প্ল্যাটফর্ম ব্যবহার করে
_Gফাংশনটি পাস করা টাইমস্ট্যাম্প স্থানীয়ভাবে সংরক্ষণ করে। - নীতি তথ্যে শুরুর রান টাইম আপডেট করুন।
- প্ল্যাটফর্ম ব্যবহার করে
getDaysFromTimeStamp ফাংশন
- কার্যকারিতা: পলিসি কার্যকর করার সময়কাল গণনা করতে দুটি টাইমস্ট্যাম্পের মধ্যে দিনের পার্থক্য গণনা করে।
- পদক্ষেপ:
- শেষের সময়টি শুরুর সময়ের আগে কিনা তা পরীক্ষা করে এবং যদি থাকে তবে 0 প্রদান করে।
- দুটি টাইমস্ট্যাম্পের মধ্যে সেকেন্ডের পার্থক্য গণনা করে এবং এটিকে দিনে রূপান্তর করে।
- দিনের পার্থক্য ফেরত দেয়।
সেভ ইউজারডেটাসলোকাল ফাংশন
- কার্যকারিতা: পলিসি কার্যকর করার সময় মূল তথ্য স্থানীয় কম্পিউটারে সংরক্ষণ করুন যাতে পলিসি পুনরায় চালু করার সময় এটি পুনরুদ্ধার করা যায়।
- পদক্ষেপ:
- প্যাকেজ অ্যাকাউন্টের সম্পদ, আয়ের পরিসংখ্যান এবং অন্যান্য তথ্য।
- প্ল্যাটফর্ম ব্যবহার করে
_Gফাংশনটি স্থানীয়ভাবে ডেটা সংরক্ষণ করে।
readUserDataLocal ফাংশন
- কার্যকারিতা: নীতিটি পুনরায় চালু হলে ডেটা পুনরুদ্ধারের জন্য স্থানীয়ভাবে সংরক্ষিত ব্যবহারকারীর ডেটা পড়ুন।
- পদক্ষেপ:
- স্থানীয়ভাবে কোনও ডেটা সংরক্ষিত আছে কিনা তা পরীক্ষা করুন।
- যদি না হয়, তাহলে ডেটা আরম্ভ করুন এবং স্থানীয়ভাবে সংরক্ষণ করুন।
- যদি তাই হয়, তাহলে এটি পড়া হবে এবং নীতিমালায় লোড করা হবে।
clearUserDataLocal ফাংশন
- কার্যকারিতা: স্থানীয়ভাবে সংরক্ষিত ব্যবহারকারীর ডেটা সাফ করুন, যা সাধারণত নীতি রিসেট বা ডিবাগিংয়ের জন্য ব্যবহৃত হয়।
- পদক্ষেপ:
- প্ল্যাটফর্ম ব্যবহার করে
_Gফাংশন স্থানীয় ডেটা সাফ করে। - লগ পরিষ্কারের কাজ।
- প্ল্যাটফর্ম ব্যবহার করে
নীতিগত মিথস্ক্রিয়া এবং কমান্ড প্রক্রিয়াকরণ
রানসিএমডি ফাংশন
- কার্যকারিতা: ইন্টারেক্টিভ ইন্টারফেসের মাধ্যমে ব্যবহারকারীদের পাঠানো কমান্ড প্রক্রিয়া করে, যেমন স্থানীয় ডেটা সাফ করা, অর্ডারের পরিমাণ পরিবর্তন করা ইত্যাদি।
- পদক্ষেপ:
- ব্যবহারকারীর পাঠানো কমান্ডটি পান।
- কমান্ডের ধরণের উপর ভিত্তি করে সংশ্লিষ্ট ক্রিয়াকলাপ সম্পাদন করুন, যেমন স্থানীয় ডেটা সাফ করা, অর্ডারের পরিমাণ পরিবর্তন করা ইত্যাদি।
- কমান্ড কার্যকর করার ফলাফল রেকর্ড করুন।
ট্রেডিং এবং অর্ডার ব্যবস্থাপনা
অর্ডারডাইরেক্টলি ফাংশন
- কার্যকারিতা: নির্দেশিকা এবং মূল্যের উপর ভিত্তি করে সরাসরি অর্ডার দিন, খোলা এবং সমাপনী কার্যক্রমকে সমর্থন করুন।
- পদক্ষেপ:
- দিকনির্দেশনা অনুসারে ট্রেডিং ফাংশন নির্বাচন করুন (কিনুন বা বিক্রি করুন)।
- ট্রেডিং দিক নির্ধারণ করুন।
- অর্ডার অপারেশনটি সম্পাদন করুন এবং ফলাফলটি ফেরত দিন।
ওপেনলং ফাংশন
- কার্যকারিতা: একটি দীর্ঘ পজিশন খুলুন এবং দাম এবং পরিমাণের উপর ভিত্তি করে একটি অর্ডার দিন।
- পদক্ষেপ:
- প্রকৃত অর্ডার পরিমাণ গণনা করুন।
- কল
orderDirectlyফাংশনটি একটি ক্রয় কার্য সম্পাদন করে।
ওপেনশর্ট ফাংশন
- কার্যকারিতা: একটি সংক্ষিপ্ত অবস্থান খুলুন এবং মূল্য এবং পরিমাণের উপর ভিত্তি করে একটি অর্ডার দিন।
- পদক্ষেপ:
- প্রকৃত অর্ডার পরিমাণ গণনা করুন।
- কল
orderDirectlyফাংশনটি একটি বিক্রয় কার্যক্রম সম্পাদন করে।
কভারলং ফাংশন
- কার্যকারিতা: মূল্য এবং পরিমাণের উপর ভিত্তি করে দীর্ঘ পজিশন বন্ধ করুন এবং অর্ডার দিন।
- পদক্ষেপ:
- কল
orderDirectlyফাংশনটি একটি বিক্রয় কার্যক্রম সম্পাদন করে।
- কল
কভারশর্ট ফাংশন
- কার্যকারিতা: মূল্য এবং পরিমাণের উপর ভিত্তি করে শর্ট পজিশন বন্ধ করুন এবং অর্ডার দিন।
- পদক্ষেপ:
- কল
orderDirectlyফাংশনটি একটি ক্রয় কার্য সম্পাদন করে।
- কল
getRealOrderSize ফাংশন
- কার্যকারিতা: দাম এবং পরিমাণের উপর ভিত্তি করে প্রকৃত অর্ডারের পরিমাণ পুনঃগণনা করুন এবং মার্জিন অনুপাতের উপর ভিত্তি করে অর্ডার স্থাপনে সহায়তা করুন।
- পদক্ষেপ:
- মার্জিন অনুপাত অনুসারে অর্ডারটি দেওয়া হয়েছে কিনা তার উপর ভিত্তি করে প্রকৃত অর্ডারের পরিমাণ গণনা করুন।
- গণনা করা অর্ডারের পরিমাণ ফেরত দেয়।
ঝুঁকি ব্যবস্থাপনা এবং রিটার্ন পরিসংখ্যান
getSinglePositionMargin ফাংশন
- কার্যকারিতা: একটি একক অবস্থান দ্বারা দখল করা মার্জিন গণনা করুন।
- পদক্ষেপ:
- অবস্থানের দিক এবং পরিমাণের উপর ভিত্তি করে মার্জিন গণনা করা হয়।
- গণনার ফলাফল প্রদান করে।
getSinglePositionProfit ফাংশন
- কার্যকারিতা: একটি একক পদের আয় এবং ফলন গণনা করুন।
- পদক্ষেপ:
- অবস্থানের দিক এবং বর্তমান মূল্যের উপর ভিত্তি করে লাভ গণনা করুন।
- আয় এবং ফলন ফেরত দেয়।
ক্যালকুলেটফোর্সডপ্রাইস ফাংশন
- কার্যকারিতা: একটি পজিশনের লিকুইডেশন মূল্য গণনা করে।
- পদক্ষেপ:
- পজিশনের দিকনির্দেশনা এবং অ্যাকাউন্ট ব্যালেন্সের উপর ভিত্তি করে লিকুইডেশন মূল্য গণনা করা হয়।
- গণনার ফলাফল প্রদান করে।
getMaxOrderSize ফাংশন
- কার্যকারিতা: সর্বোচ্চ অর্ডারের পরিমাণ গণনা করুন।
- পদক্ষেপ:
- অ্যাকাউন্ট ব্যালেন্স এবং লিভারেজের উপর ভিত্তি করে সর্বোচ্চ কত পরিমাণ অর্ডার দেওয়া যেতে পারে তা গণনা করা হয়।
- গণনার ফলাফল প্রদান করে।
getAccountAsset ফাংশন
- কার্যকারিতা: পজিশন এবং উপলব্ধ ব্যালেন্স সহ মোট অ্যাকাউন্ট সম্পদ গণনা করে।
- পদক্ষেপ:
- পজিশন এবং অ্যাকাউন্ট ব্যালেন্সের উপর ভিত্তি করে মোট ইকুইটি গণনা করুন।
- গণনার ফলাফল প্রদান করে।
ক্যালকুলেটপ্রফিট ফাংশন
- কার্যকারিতা: কৌশলের রিটার্ন গণনা এবং রেকর্ড করুন।
- পদক্ষেপ:
- বর্তমান মোট রিটার্ন এবং প্রাথমিক সম্পদের মধ্যে পার্থক্য গণনা করুন।
- লাভ রেকর্ড করুন এবং পরিসংখ্যানগত চলক আপডেট করুন।
- স্থানীয়ভাবে আয়ের তথ্য সংরক্ষণ করুন।
isEnoughAssetToOrder ফাংশন
- কার্যকারিতা: অর্ডার দেওয়ার জন্য অ্যাকাউন্টের তহবিল পর্যাপ্ত কিনা তা পরীক্ষা করুন।
- পদক্ষেপ:
- অ্যাকাউন্ট ব্যালেন্সের তথ্য পান।
- লেনদেনের মুদ্রার ধরণের (USDT-ভিত্তিক বা মুদ্রা-ভিত্তিক) উপর ভিত্তি করে প্রয়োজনীয় তহবিল গণনা করুন।
- অ্যাকাউন্ট ব্যালেন্স অর্ডারের প্রয়োজনীয়তা পূরণ করে কিনা তা পরীক্ষা করুন।
- পর্যাপ্ত তহবিল আছে কিনা তা নির্দেশ করে একটি বুলিয়ান মান প্রদান করে।
ট্রেন্ড বিচার এবং ট্রেডিং লজিক
runInKLinePeriod ফাংশন
- কার্যকারিতা: K-লাইন চক্রের উপর ভিত্তি করে কৌশলগত যুক্তি কার্যকর করা হবে কিনা তা নির্ধারণ করুন।
- পদক্ষেপ:
- বর্তমান K-লাইনটি প্রক্রিয়া করা হয়েছে কিনা তা পরীক্ষা করুন।
- যদি প্রক্রিয়াজাত না করা হয়, তাহলে এটিকে প্রক্রিয়াজাত হিসাবে চিহ্নিত করুন এবং ফেরত দিন
True, অন্যথায় ফেরত দিনFalse。
ট্রেন্ড জাজমেন্ট ফাংশন (কোর ট্রেন্ড জাজমেন্ট মডিউল)
- কার্যকারিতা: প্রযুক্তিগত সূচকের উপর ভিত্তি করে বর্তমান প্রবণতা নির্ধারণ করুন। এটি সমগ্র কাঠামোর মধ্যে সবচেয়ে নমনীয় মডিউল। ব্যবহারকারীরা তাদের চাহিদা অনুযায়ী প্রবণতা নির্ধারণের জন্য বিভিন্ন প্রযুক্তিগত সূচক প্রতিস্থাপন করতে পারেন।
- বর্তমান বাস্তবায়ন: প্রবণতা নির্ধারণের জন্য EMA (এক্সপোনেনশিয়াল মুভিং এভারেজ) এবং স্ট্যান্ডার্ড ডেভিয়েশন ব্যবহার করুন।
- স্কেলেবিলিটি:এই ফাংশনটি একটি প্লাগেবল মডিউল হিসাবে ডিজাইন করা হয়েছে, এবং ব্যবহারকারীরা সহজেই এটিকে অন্যান্য প্রযুক্তিগত সূচক দিয়ে প্রতিস্থাপন করতে পারেন, যেমন:
- আরএসআই (আপেক্ষিক শক্তি সূচক):অতিরিক্ত ক্রয় এবং অতিরিক্ত বিক্রয়ের শর্ত বিচার করা
- MACD (মুভিং এভারেজ কনভারজেন্স ডাইভারজেন্স): ট্রেন্ডের টার্নিং পয়েন্টগুলি চিহ্নিত করুন
- বলিঙ্গার ব্যান্ডস:মূল্যের অস্থিরতার উপর ভিত্তি করে প্রবণতা বিচার
- KDJ সূচক: ভরবেগ এবং প্রবণতার সম্মিলিত বিচার
- মাল্টিমিটার পোর্টফোলিও: আরও সঠিক প্রবণতা বিচারের জন্য একাধিক সূচক একত্রিত করা যেতে পারে।
- পদক্ষেপ:
- EMA সূচক গণনা করুন এবং মূল্য এটি অতিক্রম করে কিনা তা নির্ধারণ করুন।
- আদর্শ বিচ্যুতির উপর ভিত্তি করে এটি একটি প্রবণতায় আছে কিনা তা নির্ধারণ করুন।
- বর্তমান ট্রেন্ড (দীর্ঘ, স্বল্প বা পরিসর) প্রদান করে।
স্টপলস ফাংশন
- কার্যকারিতা: স্টপ-লস নিয়ম অনুসারে স্টপ-লস অপারেশন সম্পাদন করুন।
- পদক্ষেপ:
- পজিশনটি স্টপ লস শর্তে পৌঁছেছে কিনা তা পরীক্ষা করুন।
- যদি এটি পৌঁছায়, তাহলে পজিশনটি বন্ধ করে দেওয়া হবে এবং স্টপ লস তথ্য রেকর্ড করা হবে।
takeProfit ফাংশন
- কার্যকারিতা: লাভ-লাভের নিয়ম অনুসারে লাভ-লাভের কার্যক্রম সম্পাদন করুন।
- পদক্ষেপ:
- পদটি লাভের শর্ত পূরণ করে কিনা তা পরীক্ষা করুন।
- যদি এটি পৌঁছায়, তাহলে পজিশনটি বন্ধ করে দেওয়া হবে এবং লাভের তথ্য রেকর্ড করা হবে।
ট্র্যাকিংটেকপ্রফিট ফাংশন
- কার্যকারিতা: কলব্যাক টেক-প্রফিট নিয়ম অনুসারে টেক-প্রফিট অপারেশনটি সম্পাদন করুন।
- পদক্ষেপ:
- পজিশনটি কলব্যাক লাভ ট্রিগারের শর্ত পূরণ করে কিনা তা পরীক্ষা করুন।
- যদি এটি পৌঁছায়, তাহলে পজিশনটি বন্ধ করে দেওয়া হবে এবং লাভের তথ্য রেকর্ড করা হবে।
অর্ডার ফাংশন
- কার্যকারিতা: ট্রেন্ড বিচারের ফলাফলের উপর ভিত্তি করে অর্ডার অপারেশন সম্পাদন করুন।
- পদক্ষেপ:
- বর্তমান অবস্থানগুলি পরীক্ষা করুন।
- ট্রেন্ড বিচারের ফলাফলের উপর ভিত্তি করে পজিশন খুলুন বা বন্ধ করুন।
কৌশলগত মূল যুক্তি
ট্রেন্ডস্ট্র্যাটেজি ফাংশন
- কার্যকারিতা: কৌশলটির মূল লজিক ফাংশন, যা ট্রেন্ড জাজমেন্ট, স্টপ লস এবং টেক প্রফিট, কলব্যাক টেক প্রফিট এবং অর্ডার অপারেশন সম্পাদনের জন্য দায়ী।
- পদক্ষেপ:
- বাজারের তথ্য পান: বর্তমান বাজার তথ্য, অবস্থান তথ্য, অ্যাকাউন্ট তথ্য এবং কে-লাইন তথ্য পান।
- অবস্থান পরীক্ষা করুন: নিশ্চিত করুন যে কোনও দীর্ঘ বা সংক্ষিপ্ত পজিশন একসাথে রাখা হচ্ছে না, অন্যথায় একটি ব্যতিক্রম করা হবে।
- কৌশলগত মিথস্ক্রিয়া: ইন্টারেক্টিভ ইন্টারফেসের মাধ্যমে ব্যবহারকারীদের দ্বারা প্রেরিত কমান্ডগুলি প্রক্রিয়া করে।
- স্ট্যাটাস বারের তথ্য মুদ্রণ: কৌশল পরিচালনার অবস্থা, অ্যাকাউন্টের তথ্য এবং অবস্থানের অবস্থা আপডেট এবং মুদ্রণ করুন।
- ক্ষতি বন্ধ: স্টপ-লস নিয়ম অনুসারে স্টপ-লস অপারেশনগুলি পরীক্ষা করুন এবং সম্পাদন করুন।
- থামো: টেক-প্রফিট নিয়ম অনুসারে টেক-প্রফিট কার্যক্রম পরীক্ষা করুন এবং সম্পাদন করুন।
- কলব্যাকে লাভ নিন: কলব্যাক টেক-প্রফিট নিয়ম অনুসারে টেক-প্রফিট কার্যক্রম পরীক্ষা করুন এবং সম্পাদন করুন।
- কে-লাইন চক্র পরীক্ষা: নিশ্চিত করুন যে কৌশলগত যুক্তি K-লাইন চক্র অনুসারে কার্যকর করা হয়েছে।
- প্রবণতা বিচার: প্রযুক্তিগত সূচকের উপর ভিত্তি করে বর্তমান প্রবণতা (দীর্ঘ, সংক্ষিপ্ত বা দোদুল্যমান) নির্ধারণ করুন।
- একটি অর্ডার রাখুন: ট্রেন্ড বিচারের ফলাফলের উপর ভিত্তি করে একটি পজিশন খুলুন বা বন্ধ করুন।
স্থিতি পর্যবেক্ষণ এবং লগ আউটপুট
printLogStatus ফাংশন
- কার্যকারিতা: কৌশল পরিচালনার অবস্থা, অ্যাকাউন্টের তথ্য এবং অবস্থানের অবস্থা মুদ্রণ করুন।
- পদক্ষেপ:
- কৌশলের সারসংক্ষেপ, অ্যাকাউন্টের তহবিল এবং অবস্থানের সারণীগত তথ্য তৈরি করুন।
- ব্যবহার
LogStatusফাংশনটি টেবিলের ডেটা স্ট্যাটাস বারে আউটপুট করে।
প্রধান কার্যাবলী এবং কৌশল বাস্তবায়ন
প্রধান ফাংশন
- কার্যকারিতা: কৌশলের প্রধান কাজ, কৌশলটি শুরু করা এবং কৌশলগত যুক্তির মাধ্যমে লুপিং করা।
- পদক্ষেপ:
- এক্সচেঞ্জ সিমুলেশন পরিবেশ শুরু করুন।
- একটি কৌশল উদাহরণ তৈরি করুন এবং ডেটা শুরু করুন।
- কৌশলগত যুক্তিটি একটি লুপে কার্যকর করা হয়, বাজার পরিস্থিতি পরীক্ষা করে এবং নিয়মিত বিরতিতে ট্রেডিং কার্যক্রম সম্পাদন করে।
ফ্রেমওয়ার্ক বৈশিষ্ট্য
- নমনীয় প্রবণতা বিচার: EMA এবং স্ট্যান্ডার্ড ডেভিয়েশন ব্যবহার করে, এই কৌশলটি নমনীয়ভাবে বাজারের প্রবণতা নির্ধারণ করতে পারে এবং বিভিন্ন বাজার পরিবেশের জন্য প্রযোজ্য। এই ফাংশনটি কেবল একটি উদাহরণ; ব্যবহারকারীরা প্রয়োজন অনুসারে প্রবণতা নির্ধারণের জন্য বিভিন্ন প্রযুক্তিগত সূচক (যেমন RSI, MACD, বলিঙ্গার ব্যান্ড ইত্যাদি) ব্যবহার করতে পারেন।
- বিভিন্ন স্টপ-লস এবং টেক-প্রফিট প্রক্রিয়া:বিভিন্ন ঝুঁকি পছন্দের ব্যবসায়ীদের চাহিদা মেটাতে স্থির শতাংশ স্টপ লস, টেক প্রফিট এবং কলব্যাক টেক প্রফিট সমর্থন করে।
- স্থানীয় তথ্য ব্যবস্থাপনা: পলিসি অপারেশন ডেটা এবং ব্যবহারকারীর ডেটা স্থানীয়ভাবে সংরক্ষণ করা হয় যাতে পুনঃসূচনা করার পরে পলিসিটি তার পূর্ববর্তী অবস্থায় পুনরুদ্ধার করা যায়।
- ইন্টারেক্টিভ কমান্ড: কমান্ড লাইনের মাধ্যমে নীতিগুলির সাথে মিথস্ক্রিয়া সমর্থন করে, ব্যবহারকারীদের জন্য নীতির পরামিতিগুলি সামঞ্জস্য করা বা নির্দিষ্ট ক্রিয়াকলাপ সম্পাদন করা সহজ করে তোলে।
প্রযোজ্যতা
এই কাঠামোটি কেবল ডিজিটাল মুদ্রা বাজারে প্রযোজ্য নয়, বরং এটি ব্যবহার করা যেতে পারেtrendJudgmentবিভিন্ন ট্রেডিং কৌশলের প্রয়োজনীয়তার সাথে খাপ খাইয়ে নেওয়ার জন্য ফাংশনটিতে কাঠামোটি সম্প্রসারিত করা যেতে পারে। এছাড়াও, উচ্চ নমনীয়তা এবং স্কেলেবিলিটি সহ স্পট মার্কেট বা বহু-বৈচিত্র্যের চুক্তির জন্য বিশেষভাবে কাঠামোটি পরিবর্তন করা যেতে পারে।
- স্পট মার্কেট সাপোর্ট: বর্তমানে, এই কাঠামোটি মূলত চুক্তি বাজারের জন্য তৈরি, এবং ভবিষ্যতে স্পট বাজারে ট্রেডিং কৌশলগুলিকে সমর্থন করার জন্য এটি সম্প্রসারিত করা যেতে পারে।
- বহু-পণ্য চুক্তি: একাধিক চুক্তির জন্য সমর্থন যোগ করার মাধ্যমে, কৌশলগুলি একই সাথে একাধিক ডিজিটাল মুদ্রা পর্যবেক্ষণ এবং বাণিজ্য করতে পারে, মূলধনের ব্যবহার উন্নত করে।
- মেশিন লার্নিং ইন্টিগ্রেশন: মেশিন লার্নিং অ্যালগরিদমের সাথে মিলিত হয়ে, এটি ট্রেন্ড বিচারের নির্ভুলতা এবং কৌশলগুলির বুদ্ধিমত্তার স্তরকে আরও উন্নত করে।
- ঝুঁকি ব্যবস্থাপনা অপ্টিমাইজেশান: কৌশলটির দৃঢ়তা উন্নত করার জন্য ঝুঁকি ব্যবস্থাপনা প্রক্রিয়াগুলিকে আরও উন্নত করুন, যেমন গতিশীলভাবে লিভারেজ অনুপাত, বহু-স্তরের স্টপ-লস এবং টেক-প্রফিট প্রক্রিয়াগুলিকে সামঞ্জস্য করা।
সারসংক্ষেপ
একটি বিস্তৃত এবং অত্যন্ত নমনীয় স্বয়ংক্রিয় ট্রেডিং সিস্টেম হিসেবে, এই কাঠামোটি ক্রিপ্টোকারেন্সি বাজারে ট্রেন্ড ট্রেডিংয়ের জন্য উপযুক্ত। ক্রমাগত অপ্টিমাইজেশন এবং সম্প্রসারণের মাধ্যমে, এটি ভবিষ্যতে ক্রিপ্টোকারেন্সি ব্যবসায়ীদের জন্য একটি মূল্যবান হাতিয়ার হয়ে উঠবে বলে আশা করা হচ্ছে, যা তাদের নিজস্ব পরিমাণগত কৌশলগুলি আরও ভালভাবে বিকাশে সহায়তা করবে। "ক্রিপ্টোকারেন্সি ট্রেন্ড স্ট্র্যাটেজি ট্রেডিং ফ্রেমওয়ার্ক" একটি বিস্তৃত কাঠামো নিয়ে গর্ব করে। কোডের দিক থেকে তুলনামূলকভাবে বড় হলেও, এটি মূলত বাস্তব-বিশ্বের ট্রেডিং দৃষ্টিকোণ থেকে ট্রেন্ড ট্রেডিংয়ের জন্য প্রয়োজনীয় মূল কার্যকরী মডিউলগুলিকে কভার করে। অতএব, এই কাঠামোটি ট্রেডিং কৌশল শেখার জন্য এবং ব্যবহারিক প্রয়োগের জন্য উল্লেখযোগ্য রেফারেন্স মান এবং ব্যবহারিক তাৎপর্য বহন করে। এর ব্যাপক কার্যকারিতা এবং নমনীয়তা এটিকে বিভিন্ন বাজার পরিবেশের সাথে খাপ খাইয়ে নিতে সক্ষম করে, শক্তিশালী সমর্থন প্রদান করে।
ইনভেন্টর প্ল্যাটফর্ম হল পরিমাণগত ট্রেডিং জ্ঞান এবং কৌশলের এক ভান্ডার, যার প্রতিটিই এর ডেভেলপারদের জ্ঞান এবং অভিজ্ঞতাকে মূর্ত করে তোলে। আমরা এখানে মূল্যবান ট্রেডিং কৌশল এবং কৌশলগুলি অন্বেষণ করার জন্য সকলকে স্বাগত জানাই। আমাদের সকল উদ্ভাবনী এবং ভাগ করে নেওয়ার ব্যবহারকারীদের ধন্যবাদ। আপনার অবদানের জন্যই এই প্ল্যাটফর্মটি পরিমাণগত ট্রেডিংয়ে শেখার এবং বিনিময়ের জন্য একটি গুরুত্বপূর্ণ স্থান হয়ে উঠেছে, যা প্রত্যেককে তাদের দক্ষতা এবং দক্ষতা উন্নত করতে সহায়তা করে।
python
'''backtest
start: 2024-11-26 00:00:00
end: 2024-12-03 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
'''
import json, talib
import numpy as np
class TrendStrategy:
def __init__(self):
# 基本设置
self._Currency = TradeCurrency
self._Interval = Interval
self._UseQuarter = UseQuarter
self._UseContract = TradeCurrency + ('.swap' if self._UseQuarter else '.quarter')
self._OnlyTrendJudgment = OnlyTrendJudgment
self._EnableMessageSend = EnableMessageSend
# 趋势判断
self._RunInKLinePeriod = RunInKLinePeriod
self._KLinePeriod = KLinePeriod
self._EmaLength = EmaLength
self._EmaCoefficient = EmaCoefficient
self._UseStddev = UseStddev
self._UseRecordsMiddleValue = UseRecordsMiddleValue
self._StddevLength = StddevLength
self._StddevDeviations = StddevDeviations
# 下单设置
self._MarginLevel = MarginLevel
self._OrderSize = OrderSize
self._OrderByMargin = OrderByMargin
self._OrderMarginPercent = OrderMarginPercent
self._PricePrecision = None
self._AmountPrecision = None
self._OneSizeInCurrentCoin = None
self._QuarterOneSizeValue = None
# 止盈止损
self._UseStopLoss = UseStopLoss
self._StopLossPercent = StopLossPercent
self._UseTakeProfit = UseTakeProfit
self._TakeProfitPercent = TakeProfitPercent
self._UseTrackingTakeProfit = UseTrackingTakeProfit
self._UsePositionRetracement = UsePositionRetracement
self._TakeProfitTriggerPercent = TakeProfitTriggerPercent
self._CallBakcPercent = CallBakcPercent
# 策略变量
self._LastBarTime = 0
self._TrendWhenTakeProfitOrStopLoss = 0
self._HadStopLoss = False
self._TriggeredTakeProfit = False
self._PeakPriceInPosition = 0
self._HadTakeProfit = False
self._PriceCrossEMAStatus = 0
# 统计变量
self._InitAsset = 0
self._ProfitLocal = 0
self._TakeProfitCount = 0
self._TradeCount = 0
self.StrategyRunTimeStampString = "strategy_run_time"
self._StrategyDatas = {"start_run_timestamp": 0, "others": ""}
self._UserDatas = None
# 相对固定参数
self._MaintenanceMarginRate = 0.004
self._TakerFee = 0.0005
self._IsUsdtStandard = False
# 获取合约信息
ticker = _C(exchange.GetTicker, self._UseContract)
marketInfo = exchange.GetMarkets()[self._UseContract]
Log('获取市场信息:', marketInfo)
self._PricePrecision = marketInfo['PricePrecision']
self._AmountPrecision = marketInfo['AmountPrecision']
self._OneSizeInCurrentCoin = marketInfo['CtVal']
self._QuarterOneSizeValue = marketInfo['CtVal']
exchange.SetCurrency(self._Currency)
exchange.SetMarginLevel(self._UseContract, self._MarginLevel)
exchange.SetPrecision(self._PricePrecision, self._AmountPrecision)
# 初始化数据
def initDatas(self):
self.saveStrategyRunTime()
self.readUserDataLocal()
self._InitAsset = self._UserDatas["init_assets"]
self._ProfitLocal = self._UserDatas["profit_local"]
self._TakeProfitCount = self._UserDatas["take_profit_count"]
self._TradeCount = self._UserDatas["trade_count"]
if self._OrderByMargin:
self.getRealOrderSize(-1, self._OrderSize)
Log("已经重新计算下单张数:", self._OrderSize)
if self._UseTakeProfit and self._UseTrackingTakeProfit:
raise Exception("止盈和回调止盈不能同时使用!")
# 设置合约
def setContract(self):
self._IsUsdtStandard = "USDT" in self._Currency
exchange.SetCurrency(self._Currency)
if self._UseQuarter:
exchange.SetContractType("quarter")
else:
exchange.SetContractType("swap")
# 保存程序起始运行时间 秒级时间戳
def saveStrategyRunTime(self):
local_data_strategy_run_time = _G(self.StrategyRunTimeStampString)
if local_data_strategy_run_time is None:
self._StrategyDatas["start_run_timestamp"] = Unix()
_G(self.StrategyRunTimeStampString, self._StrategyDatas["start_run_timestamp"])
else:
self._StrategyDatas["start_run_timestamp"] = local_data_strategy_run_time
# 设置程序起始运行时间 秒级时间戳
def setStrategyRunTime(self, timestamp):
_G(self.StrategyRunTimeStampString, timestamp)
self._StrategyDatas["start_run_timestamp"] = timestamp
# 计算两个时间戳之间的天数,参数是秒级时间戳
def getDaysFromTimeStamp(self, start_time, end_time):
if end_time < start_time:
return 0
return (end_time - start_time) // (60 * 60 * 24)
# 保存数据到本地
def saveUserDatasLocal(self):
self._UserDatas = {
"init_assets": self._InitAsset,
"profit_local": self._ProfitLocal,
"take_profit_count": self._TakeProfitCount,
"trade_count": self._TradeCount
}
# 存储到本地
_G(exchange.GetLabel(), self._UserDatas)
Log("已把所有数据保存到本地.")
# 读取用户本地数据,程序启动时候运行一次
def readUserDataLocal(self):
user_data = _G(exchange.GetLabel())
if user_data is None:
self._InitAsset = self.getAccountAsset(_C(exchange.GetPosition), _C(exchange.GetAccount), _C(exchange.GetTicker))
self._UserDatas = {
"init_assets": self._InitAsset,
"profit_local": 0,
"take_profit_count": 0,
"trade_count": 0
}
else:
self._UserDatas = user_data
# 清除用户本地数据,交互按钮点击运行
def clearUserDataLocal(self):
_G(exchange.GetLabel(), None)
Log(exchange.GetLabel(), ":已清除本地数据.")
# 策略交互
def runCmd(self):
cmd = GetCommand()
if cmd:
# 检测交互命令
Log("接收到的命令:", cmd, "#FF1CAE")
if cmd.startswith("ClearLocalData:"):
# 清除本地数据
self.clearUserDataLocal()
elif cmd.startswith("SaveLocalData:"):
# 保存数据到本地
self.saveUserDatasLocal()
elif cmd.startswith("ClearLog:"):
# 清除日志
log_reserve = cmd.replace("ClearLog:", "")
LogReset(int(log_reserve))
elif cmd.startswith("OrderSize:"):
# 修改下单张数
if self._OrderByMargin:
Log("已经使用保证金数量来下单,无法直接修改下单数量!")
else:
order_size = int(cmd.replace("OrderSize:", ""))
self._OrderSize = order_size
Log("下单张数已经修改为:", self._OrderSize)
elif cmd.startswith("OrderMarginPercent:"):
# 修改下单保证金百分比
if self._OrderByMargin:
order_margin_percent = float(cmd.replace("OrderMarginPercent:", ""))
self._OrderMarginPercent = order_margin_percent
Log("下单保证金百分比:", self._OrderMarginPercent, "%")
else:
Log("没有打开根据保证金数量下单,无法修改下单保证金百分比!")
# 交易函数
def orderDirectly(self, distance, price, amount):
tradeFunc = None
if amount <= 0:
raise Exception("设置的参数有误,下单数量已经小于0!")
if distance == "buy":
tradeFunc = exchange.Buy
elif distance == "sell":
tradeFunc = exchange.Sell
elif distance == "closebuy":
tradeFunc = exchange.Sell
else:
tradeFunc = exchange.Buy
exchange.SetDirection(distance)
return tradeFunc(price, amount)
def openLong(self, price, amount):
real_amount = self.getRealOrderSize(price, amount)
return self.orderDirectly("buy", price, real_amount)
def openShort(self, price, amount):
real_amount = self.getRealOrderSize(price, amount)
return self.orderDirectly("sell", price, real_amount)
def coverLong(self, price, amount):
return self.orderDirectly("closebuy", price, amount)
def coverShort(self, price, amount):
return self.orderDirectly("closesell", price, amount)
# 重新计算下单数量
def getRealOrderSize(self, price, amount):
real_price = price if price != -1 else _C(exchange.GetTicker).Last
if self._OrderByMargin:
if self._IsUsdtStandard:
self._OrderSize = _N(self._InitAsset * (self._OrderMarginPercent / 100) / real_price * self._MarginLevel / self._OneSizeInCurrentCoin, self._AmountPrecision) # u本位数量(杠杆放大数量)
else:
self._OrderSize = _N(self._InitAsset * (self._OrderMarginPercent / 100) * self._MarginLevel * real_price / self._QuarterOneSizeValue, self._AmountPrecision) # 币本位数量(杠杆放大数量)
else:
self._OrderSize = amount
return self._OrderSize
# 获取单个持仓占用保证金
def getSinglePositionMargin(self, position, ticker):
position_margin = 0
if len(position) > 0:
if self._IsUsdtStandard:
position_margin = position[0].Amount * self._OneSizeInCurrentCoin * ticker.Last / self._MarginLevel
else:
position_margin = position[0].Amount * self._QuarterOneSizeValue / ticker.Last / self._MarginLevel
return position_margin
# 获取单向持仓的收益和收益%
def getSinglePositionProfit(self, position, ticker):
if len(position) == 0:
return [0, 0]
price = ticker.Last
position_margin = self.getSinglePositionMargin(position, ticker)
position_profit_percent = (price - position[0].Price) / position[0].Price * self._MarginLevel if position[0].Type == PD_LONG else (position[0].Price - price) / position[0].Price * self._MarginLevel
position_profit = position_margin * position_profit_percent
return [position_profit, position_profit_percent]
# 计算强平价格
def calculateForcedPrice(self, account, position, ticker):
position_profit = 0
total_avail_balance = 0
forced_price = 0
position_margin = self.getSinglePositionMargin(position, ticker)
[position_profit, position_profit_percent] = self.getSinglePositionProfit(position, ticker)
if self._IsUsdtStandard:
total_avail_balance = account.Balance + position_margin + account.FrozenBalance - position_profit if position_profit > 0 else account.Balance + position_margin + account.FrozenBalance
if position[0].Type == PD_LONG:
forced_price = ((self._MaintenanceMarginRate + self._TakerFee) * self._MarginLevel * account.FrozenBalance - total_avail_balance) / self._OneSizeInCurrentCoin + (position[0].Amount * position[0].Price) / (position[0].Amount - (self._MaintenanceMarginRate + self._TakerFee) * position[0].Amount)
else:
forced_price = ((self._MaintenanceMarginRate + self._TakerFee) * self._MarginLevel * account.FrozenBalance - total_avail_balance) / self._OneSizeInCurrentCoin - (position[0].Amount * position[0].Price) / (-1 * position[0].Amount - (self._MaintenanceMarginRate + self._TakerFee) * position[0].Amount)
else:
total_avail_balance = account.Stocks + position_margin + account.FrozenStocks - position_profit if position_profit > 0 else account.Stocks + position_margin + account.FrozenStocks
if position[0].Type == PD_LONG:
forced_price = (self._MaintenanceMarginRate * position[0].Amount + position[0].Amount) / (total_avail_balance / self._QuarterOneSizeValue + position[0].Amount / position[0].Price)
else:
forced_price = (self._MaintenanceMarginRate * position[0].Amount - position[0].Amount) / (total_avail_balance / self._QuarterOneSizeValue - position[0].Amount / position[0].Price)
if forced_price < 0:
forced_price = 0
return forced_price
# 计算最大可下单张数
def getMaxOrderSize(self, margin_level, ticker, account):
max_order_size = 0
if self._IsUsdtStandard:
max_order_size = account.Balance * margin_level / (self._OneSizeInCurrentCoin * ticker.Last)
else:
max_order_size = account.Stocks * ticker.Last / self._QuarterOneSizeValue * margin_level
return _N(max_order_size, self._AmountPrecision)
# 获取账户资产
def getAccountAsset(self, position, account, ticker):
# 计算不同情况下的账户初始资产
account_asset = 0
position_margin = self.getSinglePositionMargin(position, ticker)
if self._IsUsdtStandard:
if len(position) > 0:
account_asset = account.Balance + account.FrozenBalance + position_margin
else:
account_asset = account.Balance + account.FrozenBalance
else:
if len(position) > 0:
account_asset = account.Stocks + account.FrozenStocks + position_margin
else:
account_asset = account.Stocks + account.FrozenStocks
return account_asset
# 收益统计
def calculateProfit(self, ticker):
# 重新获取一下账户持仓与资产
position = _C(exchange.GetPosition)
account = _C(exchange.GetAccount)
# 当前总收益 - 上一次总收益 = 本次的收益
current_profit = (self.getAccountAsset(position, account, ticker) - self._InitAsset) - self._ProfitLocal
self._ProfitLocal += current_profit
if current_profit > 0:
self._TakeProfitCount += 1
self._TradeCount += 1
LogProfit(_N(self._ProfitLocal, 4), " 本次收益:", _N(current_profit, 6))
self.saveUserDatasLocal()
# 是否还够资金下单
def isEnoughAssetToOrder(self, order_size, ticker):
is_enough = True
account = _C(exchange.GetAccount)
if self._IsUsdtStandard:
if account.Balance < order_size * ticker.Last * self._OneSizeInCurrentCoin / self._MarginLevel:
is_enough = False
else:
if account.Stocks < order_size * self._QuarterOneSizeValue / ticker.Last / self._MarginLevel:
is_enough = False
return is_enough
# 按照K线周期运行策略核心
def runInKLinePeriod(self, records):
bar_time = records[-1].Time
if self._RunInKLinePeriod and self._LastBarTime == bar_time:
return False
self._LastBarTime = bar_time
return True
# 趋势判断模块(可编辑具体指标)
def trendJudgment(self, records):
# 检查价格是否穿过均线
def checkPriceCrossEma(price, ema_value):
if self._PriceCrossEMAStatus == 0:
if price <= ema_value:
self._PriceCrossEMAStatus = -1
else:
self._PriceCrossEMAStatus = 1
elif (self._PriceCrossEMAStatus == -1 and price >= ema_value) or (self._PriceCrossEMAStatus == 1 and price <= ema_value):
self._PriceCrossEMAStatus = 2 # 完成穿过
# EMA的多空判断
ema_long = False
ema_short = False
price = records[-2].Close # 已经收盘的K线的收盘价格
ema = TA.EMA(records, self._EmaLength)
ema_value = ema[-2] # 收盘K线对应ema值
ema_upper = ema_value * (1 + self._EmaCoefficient)
ema_lower = ema_value * (1 - self._EmaCoefficient)
checkPriceCrossEma(price, ema_value)
if price > ema_upper:
ema_long = True
elif price < ema_lower:
ema_short = True
# 标准差判断
in_trend = False
if self._UseStddev:
records_data = []
for i in range(len(records)):
records_data.append((records[i].High + records[i].Low) / 2 if self._UseRecordsMiddleValue else records[i].Close)
records_data = np.array(records_data) # 将 list 转换为 np.array
stddev = np.std(records_data, ddof=1) # 使用 numpy 计算标准差
if stddev > self._StddevDeviations:
in_trend = True
else:
in_trend = True
# 趋势判断
long = in_trend and ema_long
short = in_trend and ema_short
if long:
Log("当前趋势为:多", self._EnableMessageSend and "@" or "#00FF7F")
elif short:
Log("当前趋势为:空", self._EnableMessageSend and "@" or "#FF0000")
else:
Log("当前趋势为:震荡", self._EnableMessageSend and "@" or "#007FFF")
return [long, short]
# 止损
def stopLoss(self, position, ticker):
stop_loss_price = 0
price = ticker.Last
if len(position) == 1 and self._UseStopLoss:
if position[0].Type == PD_LONG:
stop_loss_price = position[0].Price * (1 - self._StopLossPercent / 100)
if price < stop_loss_price:
self.coverLong(-1, position[0].Amount)
self.calculateProfit(ticker)
self._TrendWhenTakeProfitOrStopLoss = 1
self._HadStopLoss = True
Log("多单止损。止损价格:", _N(stop_loss_price, 6), ", 持仓价格:", _N(position[0].Price), self._EnableMessageSend and "@" or "#FF1CAE")
elif position[0].Type == PD_SHORT:
stop_loss_price = position[0].Price * (1 + self._StopLossPercent / 100)
if price > stop_loss_price:
self.coverShort(-1, position[0].Amount)
self.calculateProfit(ticker)
self._TrendWhenTakeProfitOrStopLoss = -1
self._HadStopLoss = True
Log("空单止损。止损价格:", _N(stop_loss_price, 6), ", 持仓价格:", _N(position[0].Price), self._EnableMessageSend and "@" or "#FF1CAE")
# 止盈
def takeProfit(self, position, ticker):
take_profit_price = 0
price = ticker.Last
if len(position) == 1 and self._UseTakeProfit:
if position[0].Type == PD_LONG:
take_profit_price = position[0].Price * (1 + self._TakeProfitPercent / 100)
if price > take_profit_price:
self.coverLong(-1, position[0].Amount)
self.calculateProfit(ticker)
self._TrendWhenTakeProfitOrStopLoss = 1
self._HadTakeProfit = True
Log("多单止盈。止盈价格:", _N(take_profit_price, 6), ", 持仓价格:", _N(position[0].Price), self._EnableMessageSend and "@" or "#FF1CAE")
elif position[0].Type == PD_SHORT:
take_profit_price = position[0].Price * (1 - self._TakeProfitPercent / 100)
if price < take_profit_price:
self.coverShort(-1, position[0].Amount)
self.calculateProfit(ticker)
self._TrendWhenTakeProfitOrStopLoss = -1
self._HadTakeProfit = True
Log("空单止盈。止盈价格:", _N(take_profit_price, 6), ", 持仓价格:", _N(position[0].Price), self._EnableMessageSend and "@" or "#FF1CAE")
# 回调止盈
def trackingTakeProfit(self, position, ticker):
take_profit_price = 0
trigger_price = 0
price = ticker.Last
if len(position) > 0 and self._UseTrackingTakeProfit:
if position[0].Type == PD_LONG:
# 多单持仓
if self._TriggeredTakeProfit:
# 已达到触发价格,监控是否止盈
self._PeakPriceInPosition = price if price > self._PeakPriceInPosition else self._PeakPriceInPosition # 更新价格高点
if self._UsePositionRetracement:
take_profit_price = self._PeakPriceInPosition - (self._PeakPriceInPosition - position[0].Price) * (self._CallBakcPercent / 100) # 计算回调的止盈价格
else:
take_profit_price = self._PeakPriceInPosition * (1 - self._CallBakcPercent / 100) # 计算回调的止盈价格
if price < take_profit_price:
self.coverLong(-1, position[0].Amount) # 平多
self.calculateProfit(ticker)
self._TriggeredTakeProfit = False # 复位触发标记
self._TrendWhenTakeProfitOrStopLoss = 1 # 记录止盈时候的趋势
self._HadTakeProfit = True # 记录发生了止盈
Log("多单回调止盈:持仓中价格高点:", _N(self._PeakPriceInPosition, 6), ", 止盈价格:", _N(take_profit_price, 6), ", 当前价格:", _N(price, 6),
", 持仓价格:", _N(position[0].Price, 6), self._EnableMessageSend and "@" or "#FF1CAE")
else:
# 监控是否达到回调止盈的触发价格
trigger_price = position[0].Price * (1 + self._TakeProfitTriggerPercent / 100)
if price > trigger_price:
self._TriggeredTakeProfit = True # 触发回调止盈
self._PeakPriceInPosition = price # 记录价格高点
Log("多单已达到回调止盈的触发价格:", _N(trigger_price, 6), ", 当前价格:", _N(price, 6), ", 持仓价格:", _N(position[0].Price, 6))
elif position[0].Type == PD_SHORT:
# 空单持仓
if self._TriggeredTakeProfit:
# 已达到触发价格,监控是否止盈
self._PeakPriceInPosition = price if price < self._PeakPriceInPosition else self._PeakPriceInPosition # 更新价格低点
if self._UsePositionRetracement:
take_profit_price = self._PeakPriceInPosition + (position[0].Price - self._PeakPriceInPosition) * (self._CallBakcPercent / 100) # 计算回调的止盈价格
else:
take_profit_price = self._PeakPriceInPosition * (1 + self._CallBakcPercent / 100) # 计算回调的止盈价格
if price > take_profit_price:
self.coverShort(-1, position[0].Amount) # 平空
self.calculateProfit(ticker)
self._TriggeredTakeProfit = False # 复位触发标记
self._TrendWhenTakeProfitOrStopLoss = -1 # 记录止盈时候的趋势
self._HadTakeProfit = True # 记录发生了止盈
Log("空单回调止盈:持仓中价格低点:", _N(self._PeakPriceInPosition, 6), ", 止盈价格:", _N(take_profit_price, 6), ", 当前价格:", _N(price, 6),
", 持仓价格:", _N(position[0].Price, 6), self._EnableMessageSend and "@" or "#FF1CAE")
else:
# 监控是否达到回调止盈的触发价格
trigger_price = position[0].Price * (1 - self._TakeProfitTriggerPercent / 100)
if price < trigger_price:
self._TriggeredTakeProfit = True # 触发回调止盈
self._PeakPriceInPosition = price # 记录价格低点
Log("空单已达到回调止盈的触发价格:", _N(trigger_price, 6), ", 当前价格:", _N(price, 6), ", 持仓价格:", _N(position[0].Price, 6))
# 下单
def order(self, long, short, position, ticker):
position_size = position[0].Amount if len(position) > 0 else 0
position_type = position[0].Type if len(position) > 0 else None
if long:
# 趋势多
if (self._HadStopLoss or self._HadTakeProfit) and self._TrendWhenTakeProfitOrStopLoss == 1:
# 发生了止盈止损,并且止盈止损时候趋势为多,不再做多
return
if position_size > 0 and position_type == PD_SHORT:
self.coverShort(-1, position_size)
self.calculateProfit(ticker)
elif position_size > 0 and position_type == PD_LONG:
# 多单持仓,不重复下单
return
else:
# 没有持仓,如果是首次运行或者策略重启,需要等待价格穿过一次EMA均线才下单
if self._PriceCrossEMAStatus != 2:
return
if self.isEnoughAssetToOrder(self._OrderSize, ticker):
self.openLong(-1, self._OrderSize)
self._HadStopLoss = False
self._HadTakeProfit = False
else:
raise Exception("下单金额数量不足!")
elif short:
# 趋势空
if (self._HadStopLoss or self._HadTakeProfit) and self._TrendWhenTakeProfitOrStopLoss == -1:
# 发生了止盈止损,并且止盈止损时候趋势为空,不再做空
return
if position_size > 0 and position_type == PD_LONG:
self.coverLong(-1, position_size)
self.calculateProfit(ticker)
elif position_size > 0 and position_type == PD_SHORT:
# 空单持仓,不重复下单
return
else:
# 没有持仓,如果是首次运行或者策略重启,需要等待价格穿过一次EMA均线才下单
if self._PriceCrossEMAStatus != 2:
return
if self.isEnoughAssetToOrder(self._OrderSize, ticker):
self.openShort(-1, self._OrderSize)
self._HadStopLoss = False
self._HadTakeProfit = False
else:
raise Exception("下单金额数量不足!")
# 趋势策略
def trendStrategy(self):
ticker = _C(exchange.GetTicker)
position = _C(exchange.GetPosition)
account = _C(exchange.GetAccount)
records = _C(exchange.GetRecords, self._KLinePeriod * 60)
if len(position) > 1:
Log(position)
raise Exception("同时有多空持仓!")
# 策略交互
self.runCmd()
# 状态栏信息打印
self.printLogStatus(ticker, account, position)
# 止损
self.stopLoss(position, ticker)
# 止盈
self.takeProfit(position, ticker)
# 回调止盈
self.trackingTakeProfit(position, ticker)
# 按照K线周期运行策略
if not self.runInKLinePeriod(records):
return
# 趋势判断和下单
long = False
short = False
[long, short] = self.trendJudgment(records)
if not self._OnlyTrendJudgment:
self.order(long, short, position, ticker)
# 状态栏信息打印
def printLogStatus(self, ticker, account, position):
table_overview = {
"type": "table",
"title": "策略总览",
"cols": ["开始时间", "已运行天数", "交易次数", "胜率", "预估月化%", "预估年化%"],
"rows": []
}
table_account = {
"type": "table",
"title": "账户资金",
"cols": ["当前资产", "初始资产", "可用余额", "冻结余额", "可下单张数", "收益", "收益%"],
"rows": []
}
table_position = {
"type": "table",
"title": "持仓情况",
"cols": ["交易币种", "杠杆倍数", "持仓均价", "方向", "数量", "保证金", "预估强平价格", "浮动盈亏", "浮动盈亏%"],
"rows": []
}
i = 0
# 策略总览
the_running_days = self.getDaysFromTimeStamp(self._StrategyDatas["start_run_timestamp"], Unix())
monthly_rate_of_profit = 0
if the_running_days > 1:
monthly_rate_of_profit = self._ProfitLocal / self._InitAsset / the_running_days * 30
table_overview["rows"].append([_D(self._StrategyDatas["start_run_timestamp"]), the_running_days, self._TradeCount,
0 if self._TradeCount == 0 else (str(_N(self._TakeProfitCount / self._TradeCount * 100, 2)) + "%"),
str(_N(monthly_rate_of_profit * 100, 2)) + "%", str(_N(monthly_rate_of_profit * 12 * 100, 2)) + "%"])
# 账户资金
current_asset = self.getAccountAsset(position, account, ticker)
max_order_size = self.getMaxOrderSize(self._MarginLevel, ticker, account)
asset_profit = current_asset - self._InitAsset
asset_profit_percent = asset_profit / self._InitAsset
table_account["rows"].append([_N(current_asset, 4), _N(self._InitAsset, 4), _N(account.Balance if self._IsUsdtStandard else account.Stocks, 4),
_N(account.FrozenBalance if self._IsUsdtStandard else account.FrozenStocks, 4), max_order_size, _N(asset_profit, 4),
str(_N(asset_profit_percent * 100, 2)) + "%"])
# 持仓情况
position_direction = ""
forced_cover_up_price = 0
position_profit_percent = 0
position_profit = 0
position_margin = 0
if len(position) == 0:
table_position["rows"].append(["无持仓", "-", "-", "-", "-", "-", "-", "-", "-"])
else:
position_direction = "多单" if position[0].Type == PD_LONG else "空单"
[position_profit, position_profit_percent] = self.getSinglePositionProfit(position, ticker)
position_margin = self.getSinglePositionMargin(position, ticker)
forced_cover_up_price = self.calculateForcedPrice(account, position, ticker)
table_position["rows"].append([exchange.GetCurrency(), self._MarginLevel, _N(position[0].Price, 4), position_direction, position[0].Amount,
_N(position_margin, 4), _N(forced_cover_up_price, 4), _N(position_profit, 4), str(_N((position_profit_percent * 100), 2)) + "%"])
# 打印表格
LogStatus('`' + json.dumps(table_overview) + '`\n'
+ '`' + json.dumps(table_account) + '`\n'
+ '`' + json.dumps(table_position) + '`\n')
# main
def main():
exchange.IO('simulate', True)
strategy = TrendStrategy()
strategy.setContract()
strategy.initDatas()
while True:
strategy.trendStrategy()
Sleep(strategy._Interval)
- 1