﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/css' href='https://stocksharp.com/css/style.css'?>
<?xml-stylesheet type='text/css' href='https://stocksharp.com/css/bbeditor.css'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html">Forum. StockSharp</title>
  <id>https://stocksharp.com/handlers/atom.ashx?category=forum</id>
  <rights type="text">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  <updated>2026-04-07T10:53:36Z</updated>
  <logo>https://stocksharp.com/images/logo.png</logo>
  <link href="https://stocksharp.com/handlers/atom.ashx?category=forum" rel="self" type="application/rss+xml" />
  <entry>
    <id>https://stocksharp.com/topic/10491/</id>
    <title type="text">Website Acceptable Use Policy</title>
    <published>2019-03-05T16:34:10Z</published>
    <updated>2025-11-17T09:27:04Z</updated>
    <author>
      <name>William B</name>
      <uri>https://stocksharp.com/users/7/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;b&gt;PLEASE READ THE TERMS OF THIS POLICY CAREFULLY BEFORE USING THE SITE&lt;/b&gt;&lt;br /&gt;&lt;b&gt;What&amp;#39;s in these terms?&lt;/b&gt;&lt;br /&gt;This Acceptable Use Policy sets out the content standards that apply when you upload content to our site, make contact with other users on our site, link to our site, or interact with our site in any other way.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who we are and how to contact us&lt;/b&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com" title="https://stocksharp.com"&gt;https://stocksharp.com&lt;/a&gt; is a site operated by Stocksharp LP (&amp;quot;We&amp;quot;). We are registered in Northern Ireland under number NL000703 and have our registered office at Suite 7199, 6 St Colman&amp;#39;s Park, Newry, County Down, BT34 2BX, Northern Ireland.&lt;br /&gt;To contact us, please email &lt;a href="mailto:info@stocksharp.com"&gt;info@stocksharp.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;By using our site you accept these terms&lt;/b&gt;&lt;br /&gt;By using our site, you confirm that you accept the terms of this policy and that you agree to comply with them.&lt;br /&gt;If you do not agree to these terms, you must not use our site.&lt;br /&gt;We recommend that you print a copy of these terms for future reference.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;There are other terms that may apply to you&lt;/b&gt;&lt;br /&gt;Our &lt;a href="https://stocksharp.com/forum/10490/Terms-of-Website-Use/" title="https://stocksharp.com/forum/10490/Terms-of-Website-Use/"&gt;Terms of Website Use&lt;/a&gt; also apply to your use of our site.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;We may make changes to the terms of this policy&lt;/b&gt;&lt;br /&gt;We amend these terms from time to time. Every time you wish to use our site, please check these terms to ensure you understand the terms that apply at that time. &lt;br /&gt;Prohibited uses&lt;br /&gt;You may use our site only for lawful purposes.  You may not use our site:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	In any way that breaches any applicable local, national or international law or regulation.&lt;br /&gt;&lt;li&gt;	In any way that is unlawful or fraudulent or has any unlawful or fraudulent purpose or effect.&lt;br /&gt;&lt;li&gt;	For the purpose of harming or attempting to harm minors in any way.&lt;br /&gt;&lt;li&gt;	To send, knowingly receive, upload, download, use or re-use any material which does not comply with our content standards given below.&lt;br /&gt;&lt;li&gt;	To transmit, or procure the sending of, any unsolicited or unauthorized advertising or promotional material or any other form of similar solicitation (spam).&lt;br /&gt;&lt;li&gt;	To knowingly transmit any data, send or upload any material that contains viruses, Trojan horses, worms, time-bombs, keystroke loggers, spyware, adware or any other harmful programs or similar computer code designed to adversely affect the operation of any computer software or hardware.&lt;/ul&gt;&lt;br /&gt;You also agree:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Not to reproduce, duplicate, copy or re-sell any part of our site in contravention of the provisions of our &lt;a href="https://stocksharp.com/forum/10490/Terms-of-Website-Use/" title="https://stocksharp.com/forum/10490/Terms-of-Website-Use/"&gt;Terms of Website Use&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;	Not to access without authority, interfere with, damage or disrupt:&lt;br /&gt;&lt;li&gt;	any part of our site;&lt;br /&gt;&lt;li&gt;	any equipment or network on which our site is stored; &lt;br /&gt;&lt;li&gt;	any software used in the provision of our site; or &lt;br /&gt;&lt;li&gt;	any equipment or network or software owned or used by any third party.&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Interactive services&lt;/b&gt;&lt;br /&gt;We may from time to time provide interactive services on our site, including, without limitation:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Chat rooms.&lt;br /&gt;&lt;li&gt;	Bulletin boards.&lt;br /&gt;&lt;li&gt;     Any other interactive services.&lt;/ul&gt;&lt;br /&gt;Where we do provide any interactive service, we will provide clear information to you about the kind of service offered, if it is moderated and what form of moderation is used (including whether it is human or technical).&lt;br /&gt;We will do our best to assess any possible risks for users (and in particular, for children) from third parties when they use any interactive service provided on our site, and we will decide in each case whether it is appropriate to use moderation of the relevant service (including what kind of moderation to use) in the light of those risks. However, we are under no obligation to oversee, monitor or moderate any interactive service we provide on our site, and we expressly exclude our liability for any loss or damage arising from the use of any interactive service by a user in contravention of our content standards, whether the service is moderated or not. &lt;br /&gt;The use of any of our interactive services by a minor is subject to the consent of their parent or guardian. We advise parents who permit their children to use an interactive service that it is important that they communicate with their children about their safety online, as moderation is not fool proof. Minors who are using any interactive service should be made aware of the potential risks to them. &lt;br /&gt;Where we do moderate an interactive service, we will normally provide you with a means of contacting the moderator, should a concern or difficulty arise.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Content standards&lt;/b&gt;&lt;br /&gt;These content standards apply to any and all material which you contribute to our site (&lt;b&gt;Contribution&lt;/b&gt;), and to any interactive services associated with it. &lt;br /&gt;The Content Standards must be complied with in spirit as well as to the letter. The standards apply to each part of any Contribution as well as to its whole.&lt;br /&gt;Stocksharp LP will determine, in its discretion, whether a Contribution breaches the Content Standards.&lt;br /&gt;A Contribution must:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Be accurate (where it states facts).&lt;br /&gt;&lt;li&gt;	Be genuinely held (where it states opinions).&lt;br /&gt;&lt;li&gt;	Comply with the law applicable in any country from which it is posted.&lt;/ul&gt;&lt;br /&gt;A Contribution must not:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Be defamatory of any person.&lt;br /&gt;&lt;li&gt;	Be obscene, offensive, hateful or inflammatory.&lt;br /&gt;&lt;li&gt;	Promote sexually explicit material.&lt;br /&gt;&lt;li&gt;	Promote violence.&lt;br /&gt;&lt;li&gt;	Promote discrimination based on race, sex, religion, nationality, disability, sexual orientation or age.&lt;br /&gt;&lt;li&gt;	Infringe any copyright, database right or trade mark of any other person.&lt;br /&gt;&lt;li&gt;	Be likely to deceive any person.&lt;br /&gt;&lt;li&gt;	Breach any legal duty owed to a third party, such as a contractual duty or a duty of confidence.&lt;br /&gt;&lt;li&gt;	Promote any illegal activity.&lt;br /&gt;&lt;li&gt;	Be in contempt of court.&lt;br /&gt;&lt;li&gt;	Be threatening, abuse or invade another&amp;#39;s privacy, or cause annoyance, inconvenience or needless anxiety.&lt;br /&gt;&lt;li&gt;	Be likely to harass, upset, embarrass, alarm or annoy any other person.&lt;br /&gt;&lt;li&gt;	Impersonate any person or misrepresent your identity or affiliation with any person.&lt;br /&gt;&lt;li&gt;	Give the impression that the Contribution emanates from Stocksharp LP, if this is not the case.&lt;br /&gt;&lt;li&gt;	Advocate, promote, incite any party to commit, or assist any unlawful or criminal act such as (by way of example only) copyright infringement or computer misuse.&lt;br /&gt;&lt;li&gt;	Contain a statement which you know or believe, or have reasonable grounds for believing, that members of the public to whom the statement is, or is to be, published are likely to understand as a direct or indirect encouragement or other inducement to the commission, preparation or instigation of acts of terrorism.&lt;br /&gt;&lt;li&gt;	Contain any advertising or promote any services or web links to other sites.&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Breach of this policy&lt;/b&gt;&lt;br /&gt;When we consider that a breach of this Acceptable Use Policy has occurred, we may take such action as we deem appropriate.  &lt;br /&gt;Failure to comply with this Acceptable Use Policy constitutes a material breach of the &lt;a href="https://stocksharp.com/forum/10490/Terms-of-Website-Use/" title="https://stocksharp.com/forum/10490/Terms-of-Website-Use/"&gt;Terms of Website Use&lt;/a&gt; upon which you are permitted to use our site, and may result in our taking all or any of the following actions:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Immediate, temporary or permanent withdrawal of your right to use our site.&lt;br /&gt;&lt;li&gt;	Immediate, temporary or permanent removal of any Contribution uploaded by you to our site.&lt;br /&gt;&lt;li&gt;	Issue of a warning to you.&lt;br /&gt;&lt;li&gt;	Legal proceedings against you for reimbursement of all costs on an indemnity basis (including, but not limited to, reasonable administrative and legal costs) resulting from the breach.&lt;br /&gt;&lt;li&gt;	Further legal action against you.&lt;br /&gt;&lt;li&gt;	Disclosure of such information to law enforcement authorities as we reasonably feel is necessary or as required by law.&lt;/ul&gt;&lt;br /&gt;We exclude our liability for all action we may take in response to breaches of this Acceptable Use Policy. The actions we may take are not limited to those described above, and we may take any other action we reasonably deem appropriate.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Which country&amp;#39;s laws apply to any disputes?&lt;/b&gt;&lt;br /&gt;If you are a consumer, please note that the terms of this policy, its subject matter and its formation are governed by Northern Ireland law. You and we both agree that the courts of the Northern Ireland will have exclusive jurisdiction.&lt;br /&gt;If you are a business, the terms of this policy, its subject matter and its formation (and any non-contractual disputes or claims) are governed by Northern Ireland law. We both agree to the exclusive jurisdiction of the courts of the Northern Ireland.&lt;br /&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/10492/</id>
    <title type="text">Website Privacy Policy GDPR</title>
    <published>2019-03-05T17:09:01Z</published>
    <updated>2025-11-17T09:23:26Z</updated>
    <author>
      <name>William B</name>
      <uri>https://stocksharp.com/users/7/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;Welcome to &lt;a href="https://stocksharp.com" title="https://stocksharp.com"&gt;https://stocksharp.com&lt;/a&gt;’s privacy policy. &lt;br /&gt;&lt;a href="https://stocksharp.com" title="https://stocksharp.com"&gt;https://stocksharp.com&lt;/a&gt; respects your privacy and is committed to protecting your personal data. This privacy policy will inform you as to how we look after your personal data when you visit our website (regardless of where you visit it from) and tell you about your privacy rights and how the law protects you. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.	Important information and who we are&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Purpose of this privacy policy&lt;/b&gt;&lt;br /&gt;This privacy policy aims to give you information on how &lt;a href="https://stocksharp.com" title="https://stocksharp.com"&gt;https://stocksharp.com&lt;/a&gt; collects and processes your personal data through your use of this website, including any data you may provide through this website when you purchase a product or service. &lt;br /&gt;This website is not intended for children and we do not knowingly collect data relating to children.&lt;br /&gt;It is important that you read this privacy policy together with any other privacy policy or fair processing policy we may provide on specific occasions when we are collecting or processing personal data about you so that you are fully aware of how and why we are using your data. This privacy policy supplements other notices and privacy policies and is not intended to override them. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Controller&lt;/b&gt;&lt;br /&gt;Stocksharp is the controller and responsible for your personal data (collectively referred to as &amp;quot;Stocksharp&amp;quot;, &amp;quot;we&amp;quot;, &amp;quot;us&amp;quot; or &amp;quot;our&amp;quot; in this privacy policy).&lt;br /&gt;We have appointed a data privacy manager who is responsible for overseeing questions in relation to this privacy policy. If you have any questions about this privacy policy, including any requests to exercise your legal rights, please contact the data privacy manager using the details set out below. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Contact details&lt;/b&gt;&lt;br /&gt;If you have any questions about this privacy policy or our privacy practices, please contact our data privacy manager in the following ways:&lt;br /&gt;Full name of legal entity: StockSharp LP&lt;br /&gt;Email address: &lt;a href="mailto:info@stocksharp.com"&gt;info@stocksharp.com&lt;/a&gt;&lt;br /&gt;Postal address: Suite 7199, 6 St Colman&amp;#39;s Park, Newry, County Down, BT34 2BX, Northern Ireland&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Changes to the privacy policy and your duty to inform us of changes&lt;/b&gt;&lt;br /&gt;We keep our privacy policy under regular review.  &lt;br /&gt;It is important that the personal data we hold about you is accurate and current. Please keep us informed if your personal data changes during your relationship with us.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Third-party links&lt;/b&gt;&lt;br /&gt;This website may include links to third-party websites, plug-ins and applications. Clicking on those links or enabling those connections may allow third parties to collect or share data about you. We do not control these third-party websites and are not responsible for their privacy statements. When you leave our website, we encourage you to read the privacy policy of every website you visit.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.	The data we collect about you&lt;/b&gt;&lt;br /&gt;Personal data, or personal information, means any information about an individual from which that person can be identified. It does not include data where the identity has been removed (anonymous data).&lt;br /&gt;We may collect, use, store and transfer different kinds of personal data about you which we have grouped together as follows:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Identity Data includes first name, last name, username or similar identifier, title, date of birth and.&lt;br /&gt;&lt;li&gt;	Contact Data includes billing address, address, email address and telephone numbers.&lt;br /&gt;&lt;li&gt;	Financial Data includes bank account and payment card details.&lt;br /&gt;&lt;li&gt;	Transaction Data includes details about payments to and from you and other details of products and services you have purchased from us.&lt;br /&gt;&lt;li&gt;	Technical Data includes internet protocol (IP) address, your login data, browser type and version, time zone setting and location, browser plug-in types and versions, operating system and platform, and other technology on the devices you use to access this website. &lt;br /&gt;&lt;li&gt;	Profile Data includes your username and password, purchases or orders made by you, your interests, preferences, feedback and survey responses.  &lt;br /&gt;&lt;li&gt;	Usage Data includes information about how you use our website, products and services. &lt;br /&gt;&lt;li&gt;	Marketing and Communications Data includes your preferences in receiving marketing from us and our third parties and your communication preferences.&lt;/ul&gt;&lt;br /&gt;We also collect, use and share &lt;b&gt;Aggregated Data&lt;/b&gt; such as statistical or demographic data for any purpose. Aggregated Data could be derived from your personal data but is not considered personal data in law as this data will not directly or indirectly reveal your identity. For example, we may aggregate your Usage Data to calculate the percentage of users accessing a specific website feature. However, if we combine or connect Aggregated Data with your personal data so that it can directly or indirectly identify you, we treat the combined data as personal data which will be used in accordance with this privacy policy.&lt;br /&gt;We do not collect any &lt;b&gt;Special Categories of Personal Data&lt;/b&gt; about you (this includes details about your race or ethnicity, religious or philosophical beliefs, sex life, sexual orientation, political opinions, trade union membership, information about your health, and genetic and biometric data). Nor do we collect any information about criminal convictions and offences.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;If you fail to provide personal data&lt;/b&gt;&lt;br /&gt;Where we need to collect personal data by law, or under the terms of a contract we have with you, and you fail to provide that data when requested, we may not be able to perform the contract we have or are trying to enter into with you (for example, to provide you with goods or services). In this case, we may have to cancel a product or service you have with us but we will notify you if this is the case at the time. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;3.	How is your personal data collected?&lt;/b&gt;&lt;br /&gt;We use different methods to collect data from and about you including through:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Direct interactions. You may give us your Identity, Contact and Financial Data by filling in forms or by corresponding with us by post, phone, email or otherwise. This includes personal data you provide when you:&lt;br /&gt;&lt;li&gt;	apply for our products or services;&lt;br /&gt;&lt;li&gt;	create an account on our website;&lt;br /&gt;&lt;li&gt;	subscribe to our service; &lt;br /&gt;&lt;li&gt;	give us feedback or contact us. &lt;br /&gt;&lt;li&gt;	Automated technologies or interactions. As you interact with our website, we will automatically collect Technical Data about your equipment, browsing actions and patterns. We collect this personal data by using cookies, server logs and other similar technologies. Please see our &lt;a href="https://stocksharp.com/forum/10486/INFORMATION-ABOUT-OUR-USE-OF-COOKIES/" title="https://stocksharp.com/forum/10486/INFORMATION-ABOUT-OUR-USE-OF-COOKIES/"&gt;Cookie Policy&lt;/a&gt;  for further details.&lt;br /&gt;&lt;li&gt;	Third parties or publicly available sources. We will receive personal data about you from various third parties and public sources as set out below: &lt;br /&gt;&lt;li&gt;	Technical Data from analytics providers such as Google based outside the EU. &lt;br /&gt;&lt;li&gt;	Contact, Financial and Transaction Data from providers of technical, payment and delivery services.&lt;br /&gt;&lt;li&gt;	Identity and Contact Data from data brokers or aggregators.&lt;br /&gt;&lt;li&gt;	Identity and Contact Data from publicly available sources.&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;4.	How we use your personal data&lt;/b&gt;&lt;br /&gt;We will only use your personal data when the law allows us to. Most commonly, we will use your personal data in the following circumstances:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Where we need to perform the contract we are about to enter into or have entered into with you.&lt;br /&gt;&lt;li&gt;	Where it is necessary for our legitimate interests (or those of a third party) and your interests and fundamental rights do not override those interests.&lt;br /&gt;&lt;li&gt;	Where we need to comply with a legal obligation.&lt;/ul&gt;&lt;br /&gt;Generally, we do not rely on consent as a legal basis for processing your personal data although we will get your consent before sending third party direct marketing communications to you via email or text message. You have the right to withdraw consent to marketing at any time by contacting us.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Purposes for which we will use your personal data&lt;/b&gt;&lt;br /&gt;We have set out below, in a table format, a description of all the ways we plan to use your personal data, and which of the legal bases we rely on to do so. We have also identified what our legitimate interests are where appropriate.&lt;br /&gt;Note that we may process your personal data for more than one lawful ground depending on the specific purpose for which we are using your data. Please contact us if you need details about the specific legal ground we are relying on to process your personal data where more than one ground has been set out in the table below. &lt;br /&gt;&lt;a href='https://stocksharp.com/file/108679/Table_1.png' class='lightview' data-lightview-options="skin: 'mac'" data-lightview-group='mixed'&gt;&lt;img src="https://stocksharp.com/file/108679/Table_1.png?size=800x800" alt="http://" title="http://" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href='https://stocksharp.com/file/108680/Table_2.png' class='lightview' data-lightview-options="skin: 'mac'" data-lightview-group='mixed'&gt;&lt;img src="https://stocksharp.com/file/108680/Table_2.png?size=800x800" alt="http://" title="http://" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Marketing &lt;/b&gt;&lt;br /&gt;We strive to provide you with choices regarding certain personal data uses, particularly around marketing and advertising.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Promotional offers from us &lt;/b&gt;&lt;br /&gt;We may use your Identity, Contact, Technical, Usage and Profile Data to form a view on what we think you may want or need, or what may be of interest to you. This is how we decide which products, services and offers may be relevant for you (we call this marketing). &lt;br /&gt;You will receive marketing communications from us if you have requested information from us or purchased goods or services from us and you have not opted out of receiving that marketing.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Third-party marketing &lt;/b&gt;&lt;br /&gt;We will get your express opt-in consent before we share your personal data with any third party for marketing purposes. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Opting out&lt;/b&gt;&lt;br /&gt;You can ask us or third parties to stop sending you marketing messages at any time by logging into the website and checking or unchecking relevant boxes to adjust your marketing preferences. &lt;br /&gt;Where you opt out of receiving these marketing messages, this will not apply to personal data provided to us as a result of a product/service purchase, warranty registration, product/service experience or other transactions.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Cookies&lt;/b&gt;&lt;br /&gt;You can set your browser to refuse all or some browser cookies, or to alert you when websites set or access cookies. If you disable or refuse cookies, please note that some parts of this website may become inaccessible or not function properly. For more information about the cookies we use, please see our &lt;a href="https://stocksharp.com/forum/10486/INFORMATION-ABOUT-OUR-USE-OF-COOKIES/" title="https://stocksharp.com/forum/10486/INFORMATION-ABOUT-OUR-USE-OF-COOKIES/"&gt;Cookie Policy&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Change of purpose &lt;/b&gt;&lt;br /&gt;We will only use your personal data for the purposes for which we collected it, unless we reasonably consider that we need to use it for another reason and that reason is compatible with the original purpose. If you wish to get an explanation as to how the processing for the new purpose is compatible with the original purpose, please contact us. &lt;br /&gt;If we need to use your personal data for an unrelated purpose, we will notify you and we will explain the legal basis which allows us to do so.&lt;br /&gt;Please note that we may process your personal data without your knowledge or consent, in compliance with the above rules, where this is required or permitted by law.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5.	Disclosures of your personal data&lt;/b&gt;&lt;br /&gt;We may share your personal data with the parties set out below for the purposes set out in the table above.&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Internal Third Parties as defined below. &lt;br /&gt;&lt;li&gt;	External Third Parties as defined below.&lt;br /&gt;&lt;li&gt;	Third parties to whom we may choose to sell, transfer or merge parts of our business or our assets. Alternatively, we may seek to acquire other businesses or merge with them. If a change happens to our business, then the new owners may use your personal data in the same way as set out in this privacy policy. &lt;/ul&gt;&lt;br /&gt;We require all third parties to respect the security of your personal data and to treat it in accordance with the law. We do not allow our third-party service providers to use your personal data for their own purposes and only permit them to process your personal data for specified purposes and in accordance with our instructions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;International transfers&lt;/b&gt;&lt;br /&gt;We share your personal data within the Stocksharp Group. This will involve transferring your data outside the European Economic Area (EEA).&lt;br /&gt;Whenever we transfer your personal data out of the EEA, we ensure a similar degree of protection is afforded to it by ensuring at least one of the following safeguards is implemented: &lt;br /&gt;•	We will only transfer your personal data to countries that have been deemed to provide an adequate level of protection for personal data by the European Commission. For further details, see European Commission: Adequacy of the protection of personal data in non-EU countries.&lt;br /&gt;•	Where we use providers based in the US, we may transfer data to them if they are part of the Privacy Shield which requires them to provide similar protection to personal data shared between Europe and the US. For further details, see European Commission: EU-US Privacy Shield.&lt;br /&gt;Please contact us if you want further information on the specific mechanism used by us when transferring your personal data out of the EEA. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;6.	Data security&lt;/b&gt;&lt;br /&gt;We have put in place appropriate security measures to prevent your personal data from being accidentally lost, used or accessed in an unauthorised way, altered or disclosed. In addition, we limit access to your personal data to those employees, agents, contractors and other third parties who have a business need to know. They will only process your personal data on our instructions and they are subject to a duty of confidentiality. &lt;br /&gt;We have put in place procedures to deal with any suspected personal data breach and will notify you and any applicable regulator of a breach where we are legally required to do so.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;7.	Data retention&lt;/b&gt;&lt;br /&gt;&lt;b&gt;How long will you use my personal data for?&lt;/b&gt;&lt;br /&gt;By law we have to keep basic information about our customers (including Contact, Identity, Financial and Transaction Data) for six years after they cease being customers for tax] purposes.&lt;br /&gt;In some circumstances you can ask us to delete your data: see below for further information.&lt;br /&gt;In some circumstances we will anonymise your personal data (so that it can no longer be associated with you) for research or statistical purposes, in which case we may use this information indefinitely without further notice to you. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;8.	Your legal rights&lt;/b&gt;&lt;br /&gt;Under certain circumstances, you have rights under data protection laws in relation to your personal data. Please click on the links below to find out more about these rights: &lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Request access to your personal data.&lt;br /&gt;&lt;li&gt;	Request correction of your personal data.&lt;br /&gt;&lt;li&gt;	Request erasure of your personal data.&lt;br /&gt;&lt;li&gt;	Object to processing of your personal data.&lt;br /&gt;&lt;li&gt;	Request restriction of processing your personal data.&lt;br /&gt;&lt;li&gt;	Request transfer of your personal data.&lt;br /&gt;&lt;li&gt;	Right to withdraw consent.&lt;/ul&gt;&lt;br /&gt;If you wish to exercise any of the rights set out above, please contact us. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;No fee usually required&lt;/b&gt;&lt;br /&gt;You will not have to pay a fee to access your personal data (or to exercise any of the other rights). However, we may charge a reasonable fee if your request is clearly unfounded, repetitive or excessive. Alternatively, we could refuse to comply with your request in these circumstances.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What we may need from you&lt;/b&gt;&lt;br /&gt;We may need to request specific information from you to help us confirm your identity and ensure your right to access your personal data (or to exercise any of your other rights). This is a security measure to ensure that personal data is not disclosed to any person who has no right to receive it. We may also contact you to ask you for further information in relation to your request to speed up our response.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Time limit to respond&lt;/b&gt;&lt;br /&gt;We try to respond to all legitimate requests within one month. Occasionally it could take us longer than a month if your request is particularly complex or you have made a number of requests. In this case, we will notify you and keep you updated. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;9.	Glossary&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;LAWFUL BASIS&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Legitimate Interest&lt;/u&gt;&lt;/b&gt; means the interest of our business in conducting and managing our business to enable us to give you the best service/product and the best and most secure experience. We make sure we consider and balance any potential impact on you (both positive and negative) and your rights before we process your personal data for our legitimate interests. We do not use your personal data for activities where our interests are overridden by the impact on you (unless we have your consent or are otherwise required or permitted to by law). You can obtain further information about how we assess our legitimate interests against any potential impact on you in respect of specific activities by contacting us.&lt;br /&gt;&lt;b&gt;&lt;u&gt;Performance of Contract&lt;/u&gt;&lt;/b&gt; means processing your data where it is necessary for the performance of a contract to which you are a party or to take steps at your request before entering into such a contract.&lt;br /&gt;&lt;b&gt;&lt;u&gt;Comply with a legal obligation&lt;/u&gt;&lt;/b&gt; means processing your personal data where it is necessary for compliance with a legal obligation that we are subject to.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;THIRD PARTIES&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Internal Third Parties&lt;/b&gt;&lt;br /&gt;Other companies in the Stocksharp Group and who provide IT and system administration services and undertake leadership reporting. &lt;br /&gt;&lt;b&gt;External Third Parties&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;	Service providers.&lt;br /&gt;&lt;li&gt;	Professional advisers.&lt;br /&gt;&lt;li&gt;	HM Revenue &amp;amp; Customs, regulators and other authorities .&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;YOUR LEGAL RIGHTS&lt;/b&gt;&lt;br /&gt;You have the right to:&lt;br /&gt;&lt;b&gt;&lt;u&gt;Request access&lt;/u&gt;&lt;/b&gt; to your personal data (commonly known as a &amp;quot;data subject access request&amp;quot;). This enables you to receive a copy of the personal data we hold about you and to check that we are lawfully processing it.&lt;br /&gt;&lt;b&gt;&lt;u&gt;Request correction&lt;/u&gt;&lt;/b&gt; of the personal data that we hold about you. This enables you to have any incomplete or inaccurate data we hold about you corrected, though we may need to verify the accuracy of the new data you provide to us.&lt;br /&gt;&lt;b&gt;&lt;u&gt;Request erasure&lt;/u&gt;&lt;/b&gt; of your personal data. This enables you to ask us to delete or remove personal data where there is no good reason for us continuing to process it. You also have the right to ask us to delete or remove your personal data where you have successfully exercised your right to object to processing (see below), where we may have processed your information unlawfully or where we are required to erase your personal data to comply with local law. Note, however, that we may not always be able to comply with your request of erasure for specific legal reasons which will be notified to you, if applicable, at the time of your request. &lt;br /&gt;&lt;b&gt;&lt;u&gt;Object to processing&lt;/u&gt;&lt;/b&gt; of your personal data where we are relying on a legitimate interest (or those of a third party) and there is something about your particular situation which makes you want to object to processing on this ground as you feel it impacts on your fundamental rights and freedoms. You also have the right to object where we are processing your personal data for direct marketing purposes. In some cases, we may demonstrate that we have compelling legitimate grounds to process your information which override your rights and freedoms.&lt;br /&gt;&lt;b&gt;&lt;u&gt;Request restriction of processing&lt;/u&gt;&lt;/b&gt; of your personal data. This enables you to ask us to suspend the processing of your personal data in the following scenarios: &lt;ul&gt;&lt;br /&gt;&lt;li&gt;	If you want us to establish the data&amp;#39;s accuracy.&lt;br /&gt;&lt;li&gt;	Where our use of the data is unlawful but you do not want us to erase it.&lt;br /&gt;&lt;li&gt;	Where you need us to hold the data even if we no longer require it as you need it to establish, exercise or defend legal claims. &lt;br /&gt;&lt;li&gt;	You have objected to our use of your data but we need to verify whether we have overriding legitimate grounds to use it. &lt;/ul&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Request the transfer&lt;/u&gt;&lt;/b&gt; of your personal data to you or to a third party. We will provide to you, or a third party you have chosen, your personal data in a structured, commonly used, machine-readable format. Note that this right only applies to automated information which you initially provided consent for us to use or where we used the information to perform a contract with you. &lt;br /&gt;&lt;b&gt;&lt;u&gt;Withdraw consent at any time&lt;/u&gt;&lt;/b&gt; where we are relying on consent to process your personal data. However, this will not affect the lawfulness of any processing carried out before you withdraw your consent. If you withdraw your consent, we may not be able to provide certain products or services to you. We will advise you if this is the case at the time you withdraw your consent.&lt;br /&gt;&lt;br /&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/26458/</id>
    <title type="text">Broker</title>
    <published>2024-12-08T16:11:39Z</published>
    <updated>2024-12-09T14:32:55Z</updated>
    <author>
      <name>al</name>
      <uri>https://stocksharp.com/users/101307/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">Hi,&lt;br /&gt;Does your software support Dukascopy trading? Do you have a connector to this broker?</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25905/</id>
    <title type="text">About subscription issues？</title>
    <published>2024-06-18T05:55:09Z</published>
    <updated>2024-06-18T05:58:51Z</updated>
    <author>
      <name>wujian</name>
      <uri>https://stocksharp.com/users/102370/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">What does it mean to subscribe to Pro, which does not support API？</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25708/</id>
    <title type="text">Leveraging JavaScript for Concurrent Execution of Quantitative Strategies: Encapsulating Go Functions</title>
    <published>2024-04-18T07:35:23Z</published>
    <updated>2024-04-18T07:35:23Z</updated>
    <author>
      <name>Quant</name>
      <uri>https://stocksharp.com/users/186455/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#strategy" />
    <category term="#code" />
    <category term="#program" />
    <category term="#FMZQuant" />
    <category term="#function" />
    <category term="#concurrent" />
    <category term="#account" />
    <category term="#depth" />
    <content type="html">When implementing the quantitative strategy, concurrent execution can reduce latency and improve efficiency in many cases. Taking the hedging robot as an example, we need to obtain the depth of two coins. The code executed in sequence is as follows:&lt;br /&gt;```&lt;br /&gt;var depthA = exchanges[0].GetDepth()&lt;br /&gt;var depthB = exchanges[1].GetDepth()&lt;br /&gt;```&lt;br /&gt;There is a delay in requesting a rest API. Assuming that it is 100ms, the time for obtaining the depth is actually different. If more access is required, the delay problem will become more prominent and affect the implementation of the strategy.&lt;br /&gt;&lt;br /&gt;JavaScript has no multithreading, so the Go function is encapsulated at the bottom to solve this problem. However, due to the design mechanism, the implementation is relatively cumbersome.&lt;br /&gt;```&lt;br /&gt;var a = exchanges[0].Go(&amp;quot;GetDepth&amp;quot;)&lt;br /&gt;var b = exchanges[1].Go(&amp;quot;GetDepth&amp;quot;)&lt;br /&gt;var depthA = a.wait() // Call the wait method to wait for the return of the depth result asynchronously &lt;br /&gt;var depthB = b.wait()&lt;br /&gt;```&lt;br /&gt;In most simple cases, there is nothing wrong with writing the strategy this way. However, it is noted that this process should be repeated for each strategy loop. The intermediate variables a and b are only temporary aids. If we have a lot of concurrent tasks, we need to record the corresponding relationship between a and depthA, and b and depthB. When our concurrent tasks are uncertain, the situation becomes more complex. Therefore, we want to implement a function: when writing Go concurrently, bind a variable at the same time, and when the result of concurrent operation returns, the result will be automatically assigned to the variable, thus eliminating the intermediate variable and making the program more concise. The specific implementation is as follows:&lt;br /&gt;```&lt;br /&gt;function G(t, ctx, f) {&lt;br /&gt;    return {run:function(){&lt;br /&gt;        f(t.wait(1000), ctx)&lt;br /&gt;    }}&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;We define a G function, where the parameter t is the Go function to be executed, ctx is the recording program context, and f is the specific assignment function. You will see the function later.&lt;br /&gt;&lt;br /&gt;At this time, the overall program framework can be written as similar to the &amp;quot;producer-consumer&amp;quot; model (with some differences). The producer keeps sending out tasks, and the consumer executes them concurrently. The following code is only for demonstration, not involving the program execution logic.&lt;br /&gt;```&lt;br /&gt;var Info = [{depth:null, account:null}, {depth:null, account:null}] // If we need to obtain the depth and account of the two exchanges, more information can also be put in, such as order ID, status, etc.&lt;br /&gt;var tasks = [ ] // Global list of tasks&lt;br /&gt;&lt;br /&gt;function produce(){ // Issue various concurrent tasks&lt;br /&gt;  // The logic of task generation is omitted here, for demonstration purposes only.&lt;br /&gt;  tasks.push({exchange:0, ret:&amp;#39;depth&amp;#39;, param:[&amp;#39;GetDepth&amp;#39;]})&lt;br /&gt;  tasks.push({exchange:1, ret:&amp;#39;depth&amp;#39;, param:[&amp;#39;GetDepth&amp;#39;]})&lt;br /&gt;  tasks.push({exchange:0, ret:&amp;#39;sellID&amp;#39;, param:[&amp;#39;Buy&amp;#39;, Info[0].depth.Asks[0].Price, 10]})&lt;br /&gt;  tasks.push({exchange:1, ret:&amp;#39;buyID&amp;#39;, param:[&amp;#39;Sell&amp;#39;, Info[1].depth.Bids[0].Price, 10]})&lt;br /&gt;}&lt;br /&gt;function worker(){&lt;br /&gt;    var jobs = []&lt;br /&gt;    for(var i=0;i&amp;lt;tasks.length;i++){&lt;br /&gt;        var task = tasks[i]&lt;br /&gt;        tasks.splice(i,1) // Delete executed tasks&lt;br /&gt;        jobs.push(G(exchanges[task.exchange].Go.apply(this, task.param), task, function(v, task) {&lt;br /&gt;                    Info[task.exchange][task.ret] = v // The v here is the return value of the concurrent Go function wait(), which can be experienced carefully.&lt;br /&gt;                }))&lt;br /&gt;    }&lt;br /&gt;    _.each(jobs, function(t){&lt;br /&gt;            t.run() // Execute all tasks concurrently here&lt;br /&gt;        })&lt;br /&gt;}&lt;br /&gt;function main() {&lt;br /&gt;    while(true){&lt;br /&gt;        produce()         // Send trade orders&lt;br /&gt;        worker()        // Concurrent execution&lt;br /&gt;        Sleep(1000)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;It seems that only one simple function has been implemented after going around in circles. In fact, the complexity of the code has been simplified greatly. We only need to care about what tasks the program needs to generate. The worker() program will automatically execute them concurrently and return the corresponding results. The flexibility has improved a lot.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y63snD6Pmy6pqrWmTpTdhwkWfGOGxyMi7zL7OOb6tRc_sEYfAInfieSc7UebWcoQlCbcN4us_EriJ2CQPTwEgjGem1pkUoU3urLY_s4jaGfTA6OsaMKK6dN5_5Y-qXqKADQ5oT4skJZewQq0-dG4GQ3bqaJX5aQm9roEOEufupw_o" title="https://blog.mathquant.com/2023/01/31/use-javascript-to-implement-the-concurrent-execution-of-quantitative-strategy-encapsulate-the-go-function.html"&gt;https://blog.mathquant.c...ate-the-go-function.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25706/</id>
    <title type="text">The Secret to Survival: 19 Professionals Share Their Advice on Digital Currency Trading</title>
    <published>2024-04-18T06:37:31Z</published>
    <updated>2024-04-18T06:37:31Z</updated>
    <author>
      <name>Quant</name>
      <uri>https://stocksharp.com/users/186455/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#data" />
    <category term="#market" />
    <category term="#exchange" />
    <category term="#risk" />
    <category term="#FMZQuant" />
    <category term="#tool" />
    <category term="#plan" />
    <category term="#profits" />
    <content type="html">I have never worried about the digital currency market as much as I worry about it today. The market situation is very bad. Frankly speaking, it is weakening my sleep mode, and it is destroying my work efficiency. I&amp;#39;m torn. Should I sell or hold? You&amp;#39;re in the same boat, I know.&lt;br /&gt;&lt;br /&gt;You can&amp;#39;t keep yourself away from the chart. Every 5 minutes, a small voice comes into your mind.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;quot;Look at the chart, maybe the market has changed,&amp;quot; the voice said.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;You know that the market will not change. You also know that looking at these price charts won&amp;#39;t make you feel better. But you should do it anyway. Because you have real money invested in the market, and lots of it.&lt;br /&gt;&lt;br /&gt;This is not the first time you have done this. Maybe this is the second time. No, no, it&amp;#39;s at least the third time. I know it&amp;#39;s painful.&lt;br /&gt;&lt;br /&gt;What I&amp;#39;m about to tell you next will change your trading skills forever. These contents are not only applicable to the digital currency market, but also applicable to trading in any market, especially in the bear market - as we are facing, it is very necessary. What I want to tell you is how to keep calm when the &amp;quot;fire alarm&amp;quot; flashes.&lt;br /&gt;&lt;br /&gt;I will tell you what trading skills I learned after interviewing 19 digital currency trading professionals for a week.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;The first rule of the traders&amp;#39; club is...&lt;/span&gt;&lt;br /&gt;Let&amp;#39;s start.&lt;br /&gt;&lt;br /&gt;1. Have a trading plan at all times&lt;br /&gt;&lt;br /&gt;Now it seems obvious to me.&lt;br /&gt;&lt;br /&gt;But I have changed this plan too many times. It&amp;#39;s too easy to say that you have a trading plan, because most of us have a loose definition of entry before trading. However, there is a huge difference between making a plan and sticking to it.&lt;br /&gt;&lt;br /&gt;I know you may have made the same mistake before. You often change plans at the last minute, so you buy too early or sell too late.&lt;br /&gt;&lt;br /&gt;You need to set standards. When the market appears in one way or another, you must abide by clearly defined rules. Every professional has a trading plan - they follow it faithfully.&lt;br /&gt;&lt;br /&gt;So it&amp;#39;s time for us to think like professionals. It&amp;#39;s time to make a trading plan. The trading plan can help you focus on the key points in all transactions.&lt;br /&gt;&lt;br /&gt;After making the plan, I want you to print it and paste it in the place where you do most of the transactions. It needs to be in the obvious sight. When the market meets the threshold in any of these plans, what you need to do is execute.&lt;br /&gt;&lt;br /&gt;Writing down the plan and putting it in front of you will make it more difficult to ignore.&lt;br /&gt;&lt;br /&gt;Attention: Sometimes, it is also helpful to go through some sort of fire drill-like training. For example, I often ask myself, &amp;quot;If the market crashes now, what will I do?&amp;quot; - If the answer is &amp;quot;Nothing,&amp;quot; then continue what I am doing. If the answer is &amp;quot;I will never recover&amp;quot;, please reconsider your method.&lt;br /&gt;&lt;br /&gt;2. Integrate your portfolio&lt;br /&gt;&lt;br /&gt;Browse your portfolio and separate currencies with long-term potential from currencies without long-term potential.&lt;br /&gt;&lt;br /&gt;This is a bear market. The ship may not have started to sink officially, but it will definitely go through a rough process.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Any extra weight will make you sink faster.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Henry, a trader with seven years of stock trading experience and digital currency trading experience, told me about his trading plan in the case of a sharp decline in the market.&lt;br /&gt;&lt;br /&gt;&amp;quot;Reduce your weight. In a bull market, hold your position and stick to it. In a bull market, the investment target you choose is not important - the market rises, everyone is a winner, but some people win more than others.&amp;quot;&lt;br /&gt;&lt;br /&gt;Because in such a market, everything is changing. You are taking risks with real money. If you don&amp;#39;t act quickly, you will lose them.&lt;br /&gt;&lt;br /&gt;Henry stressed how important it is to take decisive action when the market falls. Not acting in a timely manner results in everything coming to naught.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Even look at currencies that you think have potential in the long run.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Ask yourself, is the risk worth it? Because if you exit, put your money into a better investment target or you really believe that you can resist the risk of price collapse.&lt;br /&gt;&lt;br /&gt;Henry is very good at his major!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ACTION: Add this to your trading plan list, list all your currencies and their priorities. When the market collapses, where will you start to cut investment or loss?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;3. Reduce the noise&lt;br /&gt;&lt;br /&gt;You need to stay away from the nonsense of those warlocks and bullshitters.&lt;br /&gt;&lt;br /&gt;Of the 19 professional traders I spoke with, all 19 emphasized this point.&lt;br /&gt;&lt;br /&gt;Long-term profit means positioning yourself in front or behind the crowd. &lt;b&gt;Never be in the crowd.&lt;/b&gt; Stay away from chat rooms and trading forums. Each of these groups has his own motives.&lt;br /&gt;&lt;br /&gt;Many people spend their time in discussions like Slack, Reddit, Telegram, Facebook, and Discord... The list continues. You need to keep a distance from these groups. There are too many wrong messages spread, which will lead you to make hasty decisions and buy and sell too early.&lt;br /&gt;&lt;br /&gt;Your only job as a trader is to observe charts and make judgments. To make accurate judgments, it is not necessary to collect as much data as possible. Only obtain quality information, which need not be too much, but must be correct.&lt;br /&gt;&lt;br /&gt;What kind of information is quality information? Some traders suggest joining VIP groups. These are closely connected communities, and they hope to share their views and conduct better transactions as a group.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ACTION: Question your source of information. Ask yourself - is this information necessary? Do I focus on the sources of information that really help my trading actions? If not, delete them.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;4. Build your &amp;quot;star team&amp;quot;&lt;br /&gt;&lt;br /&gt;The suggestion comes from Sparky, a trader from Sweden. Sparky is 43 years old. He has a wife and two children. Due to family reasons, his trading time is limited. So he came up with an ingenious solution.&lt;br /&gt;&lt;br /&gt;Sparky has a small team of five traders. Each of them subscribed to 2-3 main sources of information. Every day, they study these resources and send the best data back to Sparky, which is everyone&amp;#39;s mission.&lt;br /&gt;&lt;br /&gt;Only the best of the information is shared.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Sparky made five times better trading decisions therefore.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;It&amp;#39;s not difficult to start!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ACTION: Go out and socialize, find a few people who make trades, and those you trust. Start group chat on Facebook Messenger or any platform you like. Each of you should study 2 - 3 reliable sources. Team members should study their sources of information every day and pass it on to only one member of the team. Don&amp;#39;t share it with everyone. Only focus on the sources that are critical to the transaction decision.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;5. Titan&amp;#39;s tools&lt;br /&gt;&lt;br /&gt;&amp;quot;Give a man a fish, and you feed him for a day. Teach a man to fish, and you feed him for a lifetime.&amp;quot; - but you can&amp;#39;t effectively &amp;quot;teach&amp;quot; when you don&amp;#39;t even have a fishing rod.&lt;br /&gt;&lt;br /&gt;Let me introduce some good &amp;quot;fishing rods&amp;quot; and help you install them. Here are some useful trading tools I found when talking with professional traders.&lt;br /&gt;&lt;br /&gt;- Trading View (Pro)&lt;br /&gt;&lt;br /&gt;TradeingView is a very good platform that can apply almost all content related to digital currency transactions.&lt;br /&gt;&lt;br /&gt;This tool will take you to a new level of experience. One of the best functions is the split screen function.&lt;br /&gt;&lt;br /&gt;The software supports up to four independent and fully interactive price charts in any window. You can control each screen, each indicator, and each chart separately.&lt;br /&gt;&lt;br /&gt;TradingView is like a task control center, controlling every currency you have as you like.&lt;br /&gt;&lt;br /&gt;- signalgroups.com&lt;br /&gt;&lt;br /&gt;We have all experienced that the price warning sounded at 4am. You are bullish on the market, but the price has been falling all night, and you&amp;#39;re about to reach the stop-loss. Your price warning sounded, but you didn&amp;#39;t wake up. In the morning, the price is deep red, and you are in a completely unprotected state. If this has not happened to you, I promise you that it will happen.&lt;br /&gt;&lt;br /&gt;This is where Signal made by Signalgroups.com can be used. You can stop profit or loss at the same time. Therefore, you can take a rest without having to pay attention to the price in front of the computer all day.&lt;br /&gt;&lt;br /&gt;If you take your transaction seriously, you must be prepared for this feature.&lt;br /&gt;&lt;br /&gt;- FMZ.com&lt;br /&gt;&lt;br /&gt;The best digital currency quantitative trading platform in the world. Now that you have read this article, I need not say more.&lt;br /&gt;&lt;br /&gt;To put it in a nutshell...&lt;br /&gt;&lt;br /&gt;Trading is a stressful job - I&amp;#39;m sure you don&amp;#39;t need me to tell you. But when you properly arm yourself with the best skills in trading, you will dominate.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;I hope these suggestions can help you - here are some key points I extracted from the sharing of these 19 traders:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. Develop a trading plan: prepare for every possibility and always have a strategy for closing your positions.&lt;br /&gt;&lt;br /&gt;2. Choose your currency wisely: invest in the currencies that can make profits only, and reduce the currencies that cannot make profits.&lt;br /&gt;&lt;br /&gt;3. Reduce noise: Be suspicious of the masses, which will affect your thinking and make it more tempting to make unreasonable decisions.&lt;br /&gt;&lt;br /&gt;4. Build a star team: find the traders you trust and let you know the situation in time.&lt;br /&gt;&lt;br /&gt;5. Use professional tools: these and your careful attention will be the biggest improvement in your trading career.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y64HlkNn4eGrZ_7PfgIyWEue3k0YZ-S8hQFGCZxzAqiRnDVdvL3MXI3UzfA42Uo0IZG9VrlLY_wZzdIKvCE3QLUSox4CeKynvu74fFWEerYFl70ZLG57UuBV-y2tDrKm7DNA6HOhvHwQPz6q89vCNwWE" title="https://blog.mathquant.com/2023/01/31/the-secret-to-survival-19-professionals-share-their-advice-on-digital-currency-trading.html"&gt;https://blog.mathquant.c...al-currency-trading.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25705/</id>
    <title type="text">Create a Bitcoin trading robot that won&amp;apos;t lose money</title>
    <published>2024-04-18T05:08:53Z</published>
    <updated>2024-04-18T05:08:53Z</updated>
    <author>
      <name>Quant</name>
      <uri>https://stocksharp.com/users/186455/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#code" />
    <category term="#robot" />
    <category term="#bitcoin" />
    <category term="#FMZQuant" />
    <category term="#programmer" />
    <category term="#visualization" />
    <category term="#AI" />
    <category term="#optimization" />
    <content type="html">&lt;span style="font-size:140%"&gt;&lt;b&gt;Let&amp;#39;s use reinforcement learning in AI to build a digital currency trading robot.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this article, we will create and apply an enhanced learning frame number to learn how to make a Bitcoin trading robot. In this tutorial, we will use the gym of OpenAI and the PPO robot from the stable-baselines library, which is a branch of the OpenAI baseline library.&lt;br /&gt;&lt;br /&gt;Thank you very much for the open source software provided by OpenAI and DeepMind for the researchers of deep learning in the past few years. If you haven&amp;#39;t seen their amazing achievements with AlphaGo, OpenAI Five, AlphaStar and other technologies, you may have been living in isolation last year, but you should check them out.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150389
" title="https://stocksharp.com/file/150389
"&gt;https://stocksharp.com/file/150389
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;AlphaStar training: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAC_xB2Ruv96xYCq6ib3_UdKLxke9smS3DThaXdIYZL074e8Zn-tD50hlVu-1Cwes6V5pNPuViynobkXVq1guvw0qpZJi969MeN_6vj_CuXCDilIxkRfgrHAooe51Gf9h_U" title="https://deepmind.com/blog/alphastar-mastering-real-time-strategy-game-starcraft-ii/
"&gt;https://deepmind.com/blo...tegy-game-starcraft-ii/
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Although we will not create anything impressive, it is still not easy to trade Bitcoin robots in daily transactions. However, as Teddy Roosevelt once said,&lt;br /&gt;&lt;br /&gt;&lt;b&gt;There is no value in anything that is too simple.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Therefore, not only should we learn to trade ourselves, but also let robots trade for us.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Plan&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. Create a gym environment for our robot to perform machine learning&lt;br /&gt;&lt;br /&gt;2. Render a simple and elegant visual environment&lt;br /&gt;&lt;br /&gt;3. Train our robot to learn a profitable trading strategy&lt;br /&gt;&lt;br /&gt;If you are not familiar with how to create gym environments from scratch, or how to simply render the visualization of these environments. Before continuing, please feel free to google an article of this kind. These two actions will not be difficult for even the most junior programmers.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Getting Started&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;In this tutorial, we will use the Kaggle dataset generated by Zielak. If you want to download the source code, it will be provided in my Github repository, along with the .csv data file. Ok, let&amp;#39;s start.&lt;br /&gt;&lt;br /&gt;First, let&amp;#39;s import all the necessary libraries. Make sure to use pip to install any libraries you are missing.&lt;br /&gt;```&lt;br /&gt;import gym&lt;br /&gt;import pandas as pd&lt;br /&gt;import numpy as np&lt;br /&gt;from gym import spaces&lt;br /&gt;from sklearn import preprocessing&lt;br /&gt;```&lt;br /&gt;Next, let&amp;#39;s create our class for the environment. We need to pass in a Pandas data frame number and an optional initial_balance and a lookback_indow_size, which will indicate the number of past time steps observed by the robot in each step. We default the commission of each transaction to 0.075%, that is, the current exchange rate of Bitmex, and default the serial parameter to false, which means that our data frame number will be traversed by random fragments by default.&lt;br /&gt;&lt;br /&gt;We also call dropna() and reset_index() on the data, first delete the row with NaN value, and then reset the index of frame number, because we have deleted the data.&lt;br /&gt;```&lt;br /&gt;class BitcoinTradingEnv(gym.Env):&lt;br /&gt;  &amp;quot;&amp;quot;&amp;quot;A Bitcoin trading environment for OpenAI gym&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;  metadata = {&amp;#39;render.modes&amp;#39;: [&amp;#39;live&amp;#39;, &amp;#39;file&amp;#39;, &amp;#39;none&amp;#39;]}&lt;br /&gt;  scaler = preprocessing.MinMaxScaler()&lt;br /&gt;  viewer = None&lt;br /&gt;def __init__(self, df, lookback_window_size=50, &lt;br /&gt;                         commission=0.00075,  &lt;br /&gt;                         initial_balance=10000&lt;br /&gt;                         serial=False):&lt;br /&gt;    super(BitcoinTradingEnv, self).__init__()&lt;br /&gt;self.df = df.dropna().reset_index()&lt;br /&gt;    self.lookback_window_size = lookback_window_size&lt;br /&gt;    self.initial_balance = initial_balance&lt;br /&gt;    self.commission = commission&lt;br /&gt;    self.serial = serial&lt;br /&gt;# Actions of the format Buy 1/10, Sell 3/10, Hold, etc.&lt;br /&gt;    self.action_space = spaces.MultiDiscrete([3, 10])&lt;br /&gt;# Observes the OHCLV values, net worth, and trade history&lt;br /&gt;    self.observation_space = spaces.Box(low=0, high=1, shape=(10, lookback_window_size + 1), dtype=np.float16)&lt;br /&gt;```&lt;br /&gt;Our action_space is represented as a group of 3 options (buy, sell or hold) here and another group of 10 amounts (1/10, 2/10, 3/10, etc.). When we choose to buy, we will buy amount * self.balance word of BTC. For selling, we will sell amount * self.btc_held worth of BTC. Of course, holding will ignore the amount and do nothing.&lt;br /&gt;&lt;br /&gt;Our observation_space is defined as a continuous floating point set between 0 and 1, and its shape is (10, lookback_window_size+1). + 1 is used to calculate the current time step. For each time step in the window, we will observe the OHCLV value. Our net worth is equal to the number of BTCs we buy or sell, and the total amount of dollars we spend or receive on these BTCs.&lt;br /&gt;&lt;br /&gt;Next, we need to write the reset method to initialize the environment.&lt;br /&gt;```&lt;br /&gt;def reset(self):&lt;br /&gt;  self.balance = self.initial_balance&lt;br /&gt;  self.net_worth = self.initial_balance&lt;br /&gt;  self.btc_held = 0&lt;br /&gt;self._reset_session()&lt;br /&gt;self.account_history = np.repeat([&lt;br /&gt;    [self.net_worth],&lt;br /&gt;    [0],&lt;br /&gt;    [0],&lt;br /&gt;    [0],&lt;br /&gt;    [0]&lt;br /&gt;  ], self.lookback_window_size + 1, axis=1)&lt;br /&gt;self.trades = []&lt;br /&gt;return self._next_observation()&lt;br /&gt;```&lt;br /&gt;Here we use self._reset_session and self._next_observation, which we haven&amp;#39;t defined yet. Let&amp;#39;s define them first.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Trade session&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150390
" title="https://stocksharp.com/file/150390
"&gt;https://stocksharp.com/file/150390
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;An important part of our environment is the concept of trading sessions. If we deploy this robot outside the market, we may never run it for more than a few months at a time. For this reason, we will limit the number of consecutive frames in self.df, which is the number of frames that our robot can see at one time.&lt;br /&gt;&lt;br /&gt;In our _reset_session method, we reset the current_step to 0 first. Next, we will set steps_left to a random number between 1 to MAX_TRADING_SESSIONS, which we will define at the top of the program.&lt;br /&gt;```&lt;br /&gt;MAX_TRADING_SESSION = 100000 ＃ ~2 months&lt;br /&gt;```&lt;br /&gt;Next, if we want to traverse the number of frames consecutively, we must set it to traverse the entire number of frames, otherwise we set frame_start to a random point in self.df and create a new data frame named active_df, which is just a slice of self.df and it&amp;#39;s getting from frame_start to frame_start + steps_left.&lt;br /&gt;```&lt;br /&gt;def _reset_session(self):&lt;br /&gt;  self.current_step = 0&lt;br /&gt;if self.serial:&lt;br /&gt;    self.steps_left = len(self.df) - self.lookback_window_size - 1&lt;br /&gt;    self.frame_start = self.lookback_window_size&lt;br /&gt;  else:&lt;br /&gt;    self.steps_left = np.random.randint(1, MAX_TRADING_SESSION)&lt;br /&gt;    self.frame_start = np.random.randint(self.lookback_window_size, len(self.df) - self.steps_left)&lt;br /&gt;self.active_df = self.df[self.frame_start - self.lookback_window_size:self.frame_start + self.steps_left]&lt;br /&gt;```&lt;br /&gt;An important side effect of traversing the number of data frames in the random slice is that our robot will have more unique data for use in long-term training. For example, if we only traverse the number of data frames in a serial way (that is, from 0 to len(df)), we will only have as many unique data points as the number of data frames. Our observation space can only use a discrete number of states at each time step.&lt;br /&gt;&lt;br /&gt;However, by traversing the slices of the data set randomly, we can create a more meaningful set of trading results for each time step in the initial data set, that is, the combination of trading behavior and price behavior seen previously to create more unique data sets. Let me give an example to explain.&lt;br /&gt;&lt;br /&gt;When the time step after resetting the serial environment is 10, our robot will always run in the data set at the same time, and there are three options after each time step: buy, sell or hold. For each of the three options, you need another option: 10%, 20%, ... or 100% of the specific implementation amount. This means that our robot may encounter one of the 10 states of any 103, a total of 1030 cases.&lt;br /&gt;&lt;br /&gt;Now back to our random slicing environment. When the time step is 10, our robot may be in any len(df) time step within the number of data frames. Assuming that the same choice is made after each time step, it means that the robot can experience the unique state of any len(df) to the 30th power in the same 10 time steps.&lt;br /&gt;&lt;br /&gt;Although this may bring considerable noise to large data sets, I believe that robots should be allowed to learn more from our limited data. We will still traverse our test data in a serial way to obtain the freshest and seemingly &amp;#39;real-time&amp;#39; data, in order to obtain a more accurate understanding through the effectiveness of the algorithm.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Observed through the eyes of a robot&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Through effective visual environment observation, it is often helpful to understand the type of functions that our robot will use. For example, here is the visualization of observable space rendered using OpenCV.&lt;br /&gt;&lt;br /&gt;Observation of OpenCV visualization environment&lt;br /&gt;&lt;br /&gt;Each line in the image represents a row in our observation_space. The first four lines of red lines with similar frequencies represent OHCL data, and the orange and yellow dots directly below represent trading volume. The fluctuating blue bar below represents the net value of the robot, while the lighter bar below represents the transaction of the robot.&lt;br /&gt;&lt;br /&gt;If you observe carefully, you can even make a candle map yourself. Below the trading volume bar is a Morse code interface, displaying the trading history. It seems that our robot should be able to learn sufficiently from the data in our observation_space, so let&amp;#39;s continue. Here, we will define the _next_observation method, we scale the observed data from 0 to 1.&lt;br /&gt;&lt;br /&gt;- It is important to extend only the data observed by the robot so far to prevent leading deviation.&lt;br /&gt;```&lt;br /&gt;def _next_observation(self):&lt;br /&gt;  end = self.current_step + self.lookback_window_size + 1&lt;br /&gt;obs = np.array([&lt;br /&gt;    self.active_df[&amp;#39;Open&amp;#39;].values[self.current_step:end],  &lt;br /&gt;    self.active_df[&amp;#39;High&amp;#39;].values[self.current_step:end],&lt;br /&gt;    self.active_df[&amp;#39;Low&amp;#39;].values[self.current_step:end],&lt;br /&gt;    self.active_df[&amp;#39;Close&amp;#39;].values[self.current_step:end],&lt;br /&gt;    self.active_df[&amp;#39;Volume_(BTC)&amp;#39;].values[self.current_step:end],])&lt;br /&gt;scaled_history = self.scaler.fit_transform(self.account_history)&lt;br /&gt;obs = np.append(obs, scaled_history[:, -(self.lookback_window_size + 1):], axis=0)&lt;br /&gt;return obs&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Take action&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;We have established our observation space, and now it is time to write our ladder function, and then take the robot&amp;#39;s scheduled action. Whenever self.steps_left == 0 for our current trading session, we will sell our BTC and call _reset_session(). Otherwise, we will set reward to the current net value. If we run out of funds, we will set done to True.&lt;br /&gt;```&lt;br /&gt;def step(self, action):&lt;br /&gt;  current_price = self._get_current_price() + 0.01&lt;br /&gt;  self._take_action(action, current_price)&lt;br /&gt;  self.steps_left -= 1&lt;br /&gt;  self.current_step += 1&lt;br /&gt;if self.steps_left == 0:&lt;br /&gt;    self.balance += self.btc_held * current_price&lt;br /&gt;    self.btc_held = 0&lt;br /&gt;    self._reset_session()&lt;br /&gt;obs = self._next_observation()&lt;br /&gt;  reward = self.net_worth&lt;br /&gt;  done = self.net_worth &amp;lt;= 0&lt;br /&gt;return obs, reward, done, {}&lt;br /&gt;```&lt;br /&gt;Taking trading action is as simple as getting current_price, determining the actions to be executed and the quantity to buy or sell. Let&amp;#39;s quickly write _take_action so that we can test our environment.&lt;br /&gt;```&lt;br /&gt;def _take_action(self, action, current_price):&lt;br /&gt;  action_type = action[0]&lt;br /&gt;  amount = action[1] / 10&lt;br /&gt;btc_bought = 0&lt;br /&gt;  btc_sold = 0&lt;br /&gt;  cost = 0&lt;br /&gt;  sales = 0&lt;br /&gt;if action_type &amp;lt; 1:&lt;br /&gt;    btc_bought = self.balance / current_price * amount&lt;br /&gt;    cost = btc_bought * current_price * (1 + self.commission)&lt;br /&gt;    self.btc_held += btc_bought&lt;br /&gt;    self.balance -= cost&lt;br /&gt;elif action_type &amp;lt; 2:&lt;br /&gt;    btc_sold = self.btc_held * amount&lt;br /&gt;    sales = btc_sold * current_price  * (1 - self.commission)&lt;br /&gt;    self.btc_held -= btc_sold&lt;br /&gt;    self.balance += sales&lt;br /&gt;```&lt;br /&gt;Finally, in the same method, we will attach the transaction to self.trades and update our net value and account history.&lt;br /&gt;```&lt;br /&gt;if btc_sold &amp;gt; 0 or btc_bought &amp;gt; 0:&lt;br /&gt;    self.trades.append({&lt;br /&gt;      &amp;#39;step&amp;#39;: self.frame_start+self.current_step,&lt;br /&gt;      &amp;#39;amount&amp;#39;: btc_sold if btc_sold &amp;gt; 0 else btc_bought,&lt;br /&gt;      &amp;#39;total&amp;#39;: sales if btc_sold &amp;gt; 0 else cost,&lt;br /&gt;      &amp;#39;type&amp;#39;: &amp;quot;sell&amp;quot; if btc_sold &amp;gt; 0 else &amp;quot;buy&amp;quot;&lt;br /&gt;    })&lt;br /&gt;self.net_worth = self.balance + self.btc_held * current_price&lt;br /&gt;  self.account_history = np.append(self.account_history, [&lt;br /&gt;    [self.net_worth],&lt;br /&gt;    [btc_bought],&lt;br /&gt;    [cost],&lt;br /&gt;    [btc_sold],&lt;br /&gt;    [sales]&lt;br /&gt;  ], axis=1)&lt;br /&gt;```&lt;br /&gt;Our robot can start a new environment now, complete the environment gradually, and take actions that affect the environment. It&amp;#39;s time to watch the trade.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Watch our robot trade&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Our rendering method can be as simple as calling print (self.net_word), but it is not interesting enough. Instead, we will draw a simple candle chart, which contains a separate chart of the trading volume column and our net worth.&lt;br /&gt;&lt;br /&gt;We will get the code in StockTrackingGraph.py from my last article and redesign it to adapt to the Bitcoin environment. You can get the code from my Github.&lt;br /&gt;&lt;br /&gt;The first change we need to make is to update self.df [&amp;#39;Date &amp;#39;] to self.df [&amp;#39;Timestamp&amp;#39;] and delete all calls to date2num, because our date is already in unix timestamp format. Next, in our rendering method, we will update the date tag to print human-readable dates instead of numbers.&lt;br /&gt;```&lt;br /&gt;from datetime import datetime&lt;br /&gt;```&lt;br /&gt;First, import the datetime library, and then we will use utcfromtimestampmethod to obtain the UTC string from each timestamp and strftime so that it is formatted as a string: Y-m-d H:M format.&lt;br /&gt;```&lt;br /&gt;date_labels = np.array([datetime.utcfromtimestamp(x).strftime(&amp;#39;%Y-%m-%d %H:%M&amp;#39;) for x in self.df[&amp;#39;Timestamp&amp;#39;].values[step_range]])&lt;br /&gt;```&lt;br /&gt;Finally, we will change self. df[&amp;#39;Volume &amp;#39;] to self. df[&amp;#39;Volume_ (BTC)&amp;#39;] to match our dataset. After completing these, we are ready. Back to our BitcoinTradingEnv, we can write rendering methods to display the chart now.&lt;br /&gt;```&lt;br /&gt;def render(self, mode=&amp;#39;human&amp;#39;, **kwargs):&lt;br /&gt;  if mode == &amp;#39;human&amp;#39;:&lt;br /&gt;    if self.viewer == None:&lt;br /&gt;      self.viewer = BitcoinTradingGraph(self.df,&lt;br /&gt;                                        kwargs.get(&amp;#39;title&amp;#39;, None))&lt;br /&gt;self.viewer.render(self.frame_start + self.current_step,&lt;br /&gt;                       self.net_worth,&lt;br /&gt;                       self.trades,&lt;br /&gt;                       window_size=self.lookback_window_size)&lt;br /&gt;```&lt;br /&gt;We can watch our robots trade Bitcoin now.&lt;br /&gt;&lt;br /&gt;Visualize our robot trading with Matplotlib&lt;br /&gt;&lt;br /&gt;The green phantom label represents the buying of BTC, and the red phantom label represents the selling. The white label in the upper right corner is the current net value of the robot, and the label in the lower right corner is the current price of Bitcoin. It&amp;#39;s simple and elegant. Now, it&amp;#39;s time to train our robots and see how much money we can make!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Training time &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;One of the criticisms I received in the previous article was lack of cross-validation and the failure to divide the data into training sets and test sets. The purpose of this is to test the accuracy of the final model on new data that has never been seen before. Although this is not the focus of that article, it is really very important. Because we use time series data, we don&amp;#39;t have many choices in cross validation.&lt;br /&gt;&lt;br /&gt;For example, a common form of cross-validation is called k-fold validation. In this validation, you divide the data into k equal groups, one by one, individually, as the test group and use the rest of the data as the training group. However, time series data are highly dependent on time, which means that subsequent data is highly dependent on previous data. So k-fold will not work, because our robot will learn from future data before trading, which is an unfair advantage.&lt;br /&gt;&lt;br /&gt;When applied to time series data, the same flaw applies to most other cross-validation strategies. Therefore, we only need to use a part of the complete data frame number as the training set from the frame number to some arbitrary indexes, and use the rest of the data as the test set.&lt;br /&gt;```&lt;br /&gt;slice_point = int(len(df) - 100000)&lt;br /&gt;train_df = df[:slice_point]&lt;br /&gt;test_df = df[slice_point:]&lt;br /&gt;```&lt;br /&gt;Next, since our environment is only set up to handle a single number of data frames, we will create two environments, one for the training data and one for the test data.&lt;br /&gt;```&lt;br /&gt;train_env = DummyVecEnv([lambda: BitcoinTradingEnv(train_df, commission=0, serial=False)])&lt;br /&gt;test_env = DummyVecEnv([lambda: BitcoinTradingEnv(test_df, commission=0, serial=True)])&lt;br /&gt;```&lt;br /&gt;Now, training our model is as simple as creating a robot using our environment and calling model.learn.&lt;br /&gt;```&lt;br /&gt;model = PPO2(MlpPolicy,&lt;br /&gt;             train_env,&lt;br /&gt;             verbose=1, &lt;br /&gt;             tensorboard_log=&amp;quot;./tensorboard/&amp;quot;)&lt;br /&gt;model.learn(total_timesteps=50000)&lt;br /&gt;```&lt;br /&gt;Here, we use tensor plates, so we can visualize our tensor flow charts easily and view some quantitative indicators about our robot. For example, the following is the discounted rewards chart of many robots with more than 200,000 time steps:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150393
" title="https://stocksharp.com/file/150393
"&gt;https://stocksharp.com/file/150393
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wow, it seems that our robot is very profitable! Our best robot can even achieve 1000x balance in 200,000 steps, and the rest will increase at least 30 times on average!&lt;br /&gt;&lt;br /&gt;At this time, I realized that there was a mistake in the environment... After fixing the bug, this is the new reward chart:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150392
" title="https://stocksharp.com/file/150392
"&gt;https://stocksharp.com/file/150392
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, some of our robots are doing well, while others are going bankrupt. However, robots with good performance can reach 10 times or even 60 times the initial balance at most. I must admit that all profitable machines are trained and tested without commission, so it is unrealistic for our robots to make any real money. But at least we found the way!&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s test our robots in the test environment (using new data they have never seen before) to see how they will behave.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150391
" title="https://stocksharp.com/file/150391
"&gt;https://stocksharp.com/file/150391
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Our well-trained robots will go bankrupt when trading new test data&lt;br /&gt;&lt;br /&gt;Obviously, we still have a lot of work to do. By simply switching models to use A2C with stable baseline instead of the current PPO2 robot, we can improve our performance on this data set greatly. Finally, according to Sean O&amp;#39;Gorman&amp;#39;s suggestion, we can update our reward function slightly, so that we can add reward to net worth, rather than just realize high net worth and stay there.&lt;br /&gt;```&lt;br /&gt;reward = self.net_worth - prev_net_worth&lt;br /&gt;```&lt;br /&gt;These two changes alone can improve the performance of the test dataset greatly, and as you can see below, we were finally able to profit on new data that were not available in the training set.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150394
" title="https://stocksharp.com/file/150394
"&gt;https://stocksharp.com/file/150394
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;But we can do better. In order to improve these results, we need to optimize our super parameters and train our robots for a longer time. It&amp;#39;s time for the GPU to start working and firing on all cylinders!&lt;br /&gt;&lt;br /&gt;So far, this article has been a little long, and we still have many details to consider, so we plan to take a rest here. In the next article, we will use Bayesian optimization to partition the best hyperparameters for our problem space and prepare for training/testing on GPU using CUDA.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;In this article, we begin to use reinforcement learning to create a profitable Bitcoin trading robot from scratch. We can complete the following tasks:&lt;br /&gt;&lt;br /&gt;1. Create a Bitcoin trading environment from scratch using OpenAI&amp;#39;s gym.&lt;br /&gt;&lt;br /&gt;2. Use Matplotlib to build the visualization of the environment.&lt;br /&gt;&lt;br /&gt;3. Use simple cross-validation to train and test our robot.&lt;br /&gt;&lt;br /&gt;4. Adjust our robots slightly to achieve profits.&lt;br /&gt;&lt;br /&gt;Although our trading robot was not as profitable as we had hoped, we are already moving in the right direction. Next time, we will ensure that our robots can consistently beat the market. We will see how our trading robots process real-time data. Please continue to follow my next article and Viva Bitcoin!&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y61BeAcaxEvK7y74tUKh9Dc6P6huJd4NkgULHYBN66HApDeOTVDwt37lQqVGu0Cx5rUGWuAlBmiMzfGlsdvJUY0E" title="https://blog.mathquant.com/2023/02/01/create-a-bitcoin-trading-robot-that-wont-lose-money.html"&gt;https://blog.mathquant.c...hat-wont-lose-money.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25704/</id>
    <title type="text">From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return</title>
    <published>2024-04-18T03:37:38Z</published>
    <updated>2024-04-18T03:37:38Z</updated>
    <author>
      <name>Quant</name>
      <uri>https://stocksharp.com/users/186455/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#arbitrage" />
    <category term="#strategy" />
    <category term="#return" />
    <category term="#asset" />
    <category term="#trend" />
    <category term="#position" />
    <category term="#FMZQuant" />
    <category term="#CTA" />
    <content type="html">&lt;span style="font-size:140%"&gt;&lt;b&gt;Preface&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;Why should I take this course?&lt;/b&gt;&lt;br /&gt;What do you gain from taking this course? First of all, this course is based on JavaScript and Python programming languages. Language is only a technology. Finally, we should apply this technology into an industry. Quantitative trading is an emerging industry, which is currently in a rapid development stage and has a large demand for talents.&lt;br /&gt;&lt;br /&gt;Through the systematic learning of this course, you can have a deeper understanding of the field of quantitative trading. If you are a student preparing to enter the field of quantitative trading, it will also help you. If you are a stock or futures investment enthusiast, then quantitative trading can assist your subjective trading. By developing trading strategies, you can gain profits in the financial market, and also broaden the channels and platforms for your investment and financial management.&lt;br /&gt;&lt;br /&gt;Before that, let me talk about my personal trading experience. I am not a finance major, I studied statistics. At first, I began to trade stocks subjectively in my school days. Later, I became a quantitative trading practitioner of domestic private equity funds, mainly engaged in strategy research and strategy development.&lt;br /&gt;&lt;br /&gt;I have been trading in this circle for more than ten years, and have developed various types of strategies. My investment philosophy is: risk control is above all else and focuses on absolute returns. The topic of our topic is: from quantitative trading to asset management - CTA strategy development for absolute return.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;1. Futures CTA strategy money-making logic&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;1.1 Understanding Futures CTA&lt;/b&gt;&lt;br /&gt;Someone may ask what CTA is? What exactly is the CTA? CTA is called commodity trading advisors in foreign countries and investment manager in China. The traditional CTA is to collect the funds of the majority of investors, then entrust them to professional investment institutions, and finally invest in stock index futures, commodity futures, and treasury bond futures through trading advisers (namely CTA).&lt;br /&gt;&lt;br /&gt;But in fact, with the continuous development and expansion of the global futures market, the concept of CTA is also expanding, and its scope is far beyond traditional futures. It can invest not only in the futures market, but also in the interest rate market, the stock market, the foreign exchange market and the option market. As long as there is a certain amount of historical data for this variety, it can develop corresponding CTA strategies based on these historical data.&lt;br /&gt;&lt;br /&gt;As early as the 1980s, the electronic trading technology was not mature. At that time, most traders judged the future trend of commodity futures by drawing technical indicators manually, such as William index, KDJ, RSI, MACD, CCI, etc. Later, traders set up a special CTA fund to help customers manage assets. It was not until the popularization of electronic trading in the 1980s that the real CTA fund began to appear.&lt;br /&gt;&lt;br /&gt;*Changes in CTA fund management size*&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150373
" title="https://stocksharp.com/file/150373
"&gt;https://stocksharp.com/file/150373
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;In billions of dollars&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s look at the chart above. Especially with the rise of quantitative trading, the scale of global CTA funds has increased from US $130.6 billion in 2005 to more than US $300 billion in 2015. CTA strategy has also become one of the mainstream investment strategies of global hedge funds.&lt;br /&gt;&lt;br /&gt;Rising alongside the size is the performance of CTA funds. Let&amp;#39;s look at the Barclays CTA index in the chart below. The Barclay CTA index is a representative industry benchmark for global commodity trading advisers. From the end of 1979 to the end of 2016, the cumulative return of the Barclay CTA Fund Index was up to 28.95 times, the annualized return was 9.59%, the Sharp ratio was 0.37, and the maximum withdrawal was 15.66%.&lt;br /&gt;&lt;br /&gt;Because in the asset allocation portfolio, the CTA strategy usually maintains very low correlation with other strategies. As shown in the red circle below, during the global stock bear market from 2000 to 2002 and the global subprime crisis in 2008, the Barclay CTA fund index not only did not fall but also achieved positive returns. When the stock market and bond market were in crisis, CTA could provide strong returns. In addition, we can see that the profit level of the Barclay Commodity CTA Index since 1980 has been stronger than the S&amp;amp;P 500, and the withdrawal is also much lower than the S&amp;amp;P 500.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150375
" title="https://stocksharp.com/file/150375
"&gt;https://stocksharp.com/file/150375
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The development of CTA in China has only been in the past ten years, but the momentum is very strong. This is mostly due to the relatively open trading environment of domestic commodity futures, the low threshold of trading funds, the use of margin system to trade in both long and short positions, the low transaction costs, the more advanced technical structure of the exchange compared with stocks, and the easier system trading.&lt;br /&gt;&lt;br /&gt;Since 2010, CTA funds have mainly existed in the form of private funds. With the gradual opening of the investment scope of the fund special account in domestic policies, CTA funds began to exist in the form of fund special account. Its more transparent and open operation mode has also become a necessary tool for more investors to allocate assets.&lt;br /&gt;&lt;br /&gt;CTA strategies are also more suitable for individual traders than other trading strategies in terms of ease of entry, capital threshold, execution of trading strategies, and API connectivity. Domestic futures contracts are very small. For example, corn or soybean meal can be traded for thousands of yuan, and there is almost no capital threshold. In addition, because some CTA strategies come from traditional technical analysis, it is relatively easy compared with other strategies.&lt;br /&gt;&lt;br /&gt;The design process of CTA strategy is also relatively simple. First, the historical data is processed initially, and then input into the quantitative model. The quantitative model includes the trading strategy formed by mathematical modeling, programming design and other tools, and the trading signal is generated by calculating and analyzing these data. Of course, in actual development, it is not as simple as the above chart. Here we just give you an overall concept.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.2 Type of futures CTA strategy&lt;/b&gt;&lt;br /&gt;From the perspective of trading strategy, CTA strategy is also diversified: it can be a trend strategy or an arbitrage strategy; It can be a large-period medium and long-term strategy, or an intraday short term strategy; The strategy logic can be based on technical analysis or fundamental analysis; It can be a subjective transaction or system transaction.&lt;br /&gt;&lt;br /&gt;CTA strategy has different classification methods. According to the transaction method, it can be divided into subjective transaction and system transaction. The development of foreign CTA strategy is relatively advanced, and the CTA strategy of system transaction has been close to 100%. According to the analysis method, it can be divided into basic analysis and technical analysis. According to the source of income, it can be divided into trend trading and oscillatory trading.&lt;br /&gt;&lt;br /&gt;In general, the CTA strategy accounts for about 70% of the total trading market, the trend strategy accounts for about 25%, and the counter trend or trend reversal strategy accounts for about 5%. Among them, the trend strategy with the largest proportion can be divided into high-frequency trading, intra-day trading, short- and medium-term trading, and medium- and long-term trading according to the position period.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;High-frequency market making strategy&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;At present, there are two mainstream high-frequency trading strategies on the market: one is high-frequency market making strategy, the other is high-frequency arbitrage strategy. Market making strategy is to provide liquidity in the trading market. That is to say, in the trading market with a market maker, if someone wants to trade, the market maker must ensure that his order can be traded. If there is insufficient liquidity in the market and the order cannot be traded, the market maker must buy or sell the counterparty&amp;#39;s order.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;High-frequency arbitrage strategy&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;High frequency arbitrage refers to trading two highly correlated stocks or ETF and ETF portfolio. According to the calculation method of ETF, the expected price of an ETF can be calculated in the same way. The ETF index price may subtract the ETF expected price to get a price difference. Usually, the price difference will run in a price channel. If the price difference breaks through the upper and lower channels, you can trade the price difference, wait for the return of the price difference, and earn income from it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;Intraday strategy&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;In the literal sense, as long as there is no position overnight, it can be called intra-day trading strategy. Due to the short holding period of intraday trading, it is usually impossible to make profits immediately after entering the market, and then leave the market quickly. Therefore, this trading mode bears low market risk. However, because the market changes rapidly in a short period of time, the intra-day strategy usually has higher requirements for traders.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Medium and long-term strategy&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;In theory, the longer the holding period is, the greater the strategic capacity and the lower the risk-return ratio will be. Especially in institutional transactions, because of the limited capacity of short-term strategies, large funds cannot enter and exit the market in a short period of time, more long-term strategies will be allocated. Generally, the position period is several days and months, or even longer.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;CTA strategy data&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Generally speaking, the CTA strategy is studied with minute, hour and daily data, which include: opening price, highest price, lowest price, closing price, trading volume, etc; Only a few CTA strategies will use Tick data, such as buy price, sell price, buy volume, sell volume and other in-depth data in L2 data.&lt;br /&gt;&lt;br /&gt;As for the basic idea of CTA strategy, the first thing we think of is based on traditional technical indicators, because there are many public reference materials in this area, and the logic is usually simple, most of which are based on statistical principles. For example, we are familiar with various technical indicators: MA, SMA, EMA, MACD, KDJ, RSI, BOLL, W&amp;amp;R, DMI, ATR, SAR, BIAS, OBV, etc.&lt;br /&gt;&lt;br /&gt;There are also some classic trading models on the market, which can also be used for reference and improved, including: multiple moving average combination, DualThrust, R-Breaker, Turtle trading method, grid trading method, etc.&lt;br /&gt;&lt;br /&gt;All of these are trading strategies based on traditional technical analysis. The process is to extract factors or trading conditions with probability advantages according to historical data and correct trading concepts, and assume that the market will still have such laws in the future. Finally, the trading strategy is realized by code and fully automatic trading. Open positions, stop profits, stop losses, increase positions, reduce positions, etc., which generally do not require manual intervention. In fact, it is a strategy of buying the winners by using the positive autocorrelation coefficient of the price time series.&lt;br /&gt;&lt;br /&gt;The biggest advantage of CTA strategy is that no matter whether the current market is rising or falling, it can obtain absolute returns, especially when the market is rapidly changing, or the market trend is obviously smooth, the advantage of the strategy is obvious, in short, if there is a trend, there is a gain. However, if the market is in a volatile situation or the trend is not obvious, the strategy may buy at a high point and sell at a low point, and stop the loss back and forth.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.3 Profit principle of futures CTA strategy&lt;/b&gt;&lt;br /&gt;The futures CTA strategy is profitable mainly because of the following points:&lt;br /&gt;&lt;br /&gt;- 1. There is reflexivity in the price trend, which always continues in the way of trend. When investors observe that the price rises, they will follow the trend and buy, resulting in a further rise in the price. The same is true of price decreasing. Because investors are more irrational, sometimes we can see that the price rises abnormally and falls abnormally.&lt;br /&gt;- 2. Each investor has an asymmetrical tolerance for the ratio of profit to loss and a different tolerance for risk. For most retail investors, they are more inclined to choose a more conservative homeopathic trading method, and the market is also more prone to the trend.&lt;br /&gt;- 3. The formation of the price is determined by the transaction. It is true that the transaction is driven by people, but human nature is difficult to change. This is the reason why the fixed pattern will recur. The strategy is effective in the historical data backtesting, which indicates that it may also be effective in the future.&lt;br /&gt;&lt;br /&gt;In addition, the trading feature of trend tracking is to lose a small amount of money when there is no market, and make great fortune when the market comes. However, people who have done trading know that the market is volatile most of the time, and only in a small amount of time is the trend market. Therefore, the trend tracking strategy has a low winning rate in trading, but the overall profit and loss of each transaction is relatively large.&lt;br /&gt;&lt;br /&gt;Because the trend tracking strategy is unstable in terms of income, many investment institutions will use multiple varieties and strategies to build a portfolio, which will also be configured with a certain amount of reversal strategies. The reverse strategy is an autocorrelation with a negative coefficient in the time series of prices, i.e., high selling and low taking.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Correlation between CTA and traditional assets&lt;/em&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150376
" title="https://stocksharp.com/file/150376
"&gt;https://stocksharp.com/file/150376
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s look at the above chart. Theoretically, various strategies with different styles or relatively low correlation will sometimes the same and sometimes different trading signals at the same time when facing various changes in market prices. As multiple return curves overlap each other, the overall return is complementary, and the return curve will become more flat, thus reducing the volatility of returns.&lt;br /&gt;&lt;br /&gt;From the above point of view, it can be concluded that it is better to develop multiple moderate sub-strategies than to develop a master strategy. How to control these strategies? Here we can learn from the random forest algorithm in machine learning. The random forest is not an independent algorithm, it is a decision framework containing multiple decision trees. It is equivalent to the parent strategy above the sub-strategy of the decision tree. The substrategy cluster is organized and controlled through the parent strategy.&lt;br /&gt;&lt;br /&gt;Next, we need to design a parent strategy. We can evaluate the liquidity, profitability and stability of each variety in the entire commodity futures market to screen out the commodity futures variety portfolio with low volatility of earnings, and then conduct industry neutral screening, further reduce the overall volatility through the industry dispersion of the portfolio, and finally build the actual commodity futures multi-variety portfolio through market value matching for trading.&lt;br /&gt;&lt;br /&gt;Each variety can also be configured with multi-parameter strategies, and it can select the parameter combination with good performance in the backtest. When the market trend is obvious, the multi-parameter strategies will generally perform consistently, which is equivalent to adding positions; When the market is in a volatile situation, the performance of multiple sets of parameter strategies will usually be inconsistent, so that they can hedge risks by going long or short, respectively, which is equivalent to reducing positions. This can further reduce the maximum backtest rate of the portfolio, while maintaining the overall rate of return unchanged.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;2. Classic futures CTA strategy example&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Newton once said: If I see further than others, it is because I stand on the shoulders of giants.&lt;br /&gt;&lt;br /&gt;The CTA strategies publicly available on the market include the SMA strategy, the Bollinger band strategy, the turtle trading rules, the momentum strategy, the arbitrage strategy, and so on. Quantitative trading strategies have one characteristic, that is, they will slowly fail once they are made public. But this does not affect us to learn from these strategies and learn from the essence of them, so that we can solve problems on the shoulders of giants.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.1 Analysis of futures fundamentals (inventory, basis difference, price)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The fundamental analysis does not need to care about the short-term price trend. It is believed that the value will be reflected in the price ultimately. It is more about analyzing the factors behind the price to determine how much the variety is worth. Generally, the top-down analysis method is adopted: from macro factors, variety factors and other factors.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150377
" title="https://stocksharp.com/file/150377
"&gt;https://stocksharp.com/file/150377
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We can see from the above chart that there are many factors that affect commodity prices, and these data are changing constantly. It is beyond the ability of individual retail investors to obtain these huge data, let alone objective analysis.&lt;br /&gt;&lt;br /&gt;In fact, the fundamental analysis of commodity futures is not to analyze all the factors. We only need to grasp the core elements of fundamental analysis to find out the rules from the complex information.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Macro factors&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Macroeconomic data is complex and changeable. Every day, every moment, there are many economic data published, from national politics, central banks, investment banks, official and unofficial. In addition to the political and economic crisis, macro-analysis is a good material for chatting, but not practical. Peter Lynch, a famous fund management expert in the United States, once said: &amp;quot;I spend no more than 15 minutes on the analysis of the economic situation every year&amp;quot;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Variety factor&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;In the fundamental analysis, the variety analysis is mainly to analyze premium and discount, supply and demand relationship, commodity inventory, industrial profit, etc. It can be said that mastering the variety factor analysis of commodity futures can judge most of the market trend.&lt;br /&gt;&lt;br /&gt;As friends who have done futures know, domestic commodity futures can be simply divided into industrial products and agricultural products. The analysis methods of industrial products and agricultural products are different. We will elaborate on the two aspects of supply and demand. In industrial products, supply is relatively stable. Unless there is a major technological breakthrough, production capacity is unlikely to change significantly in a short period of time. Therefore, the main factor affecting the price of industrial products is demand. The demand for agricultural products is relatively stable. In the long run, the demand for agricultural products changes, but in the short run, the demand for agricultural products tends to be stable, so the main factor affecting the price of agricultural products is supply.&lt;br /&gt;&lt;br /&gt;Therefore, according to the laws of economics, it is the relationship between supply and demand that determines the price of goods ultimately. In theory, as long as the data of supply and demand can be obtained, the future price of goods can be determined. For industrial products, the supply data is easy to obtain, but it is difficult to obtain the demand data. For agricultural products, the demand data is easy to obtain, and it is difficult to obtain the supply data.&lt;br /&gt;&lt;br /&gt;In fact, we can further subtract. The mutual result of supply and demand in the economic market is inventory. We can judge the strength of the relationship between market supply and demand through inventory data. If the inventory of a commodity is very high, it means that the market supply is greater than the demand, and the commodity price will decrease on the premise that the external conditions remain unchanged. If the inventory of a commodity is very low, it means that the market demand is greater than supply, and the commodity price will increase on the premise that the external conditions remain unchanged.&lt;br /&gt;&lt;br /&gt;In addition to analyzing commodity inventory, we also need to analyze the price difference between the spot market and the futures market, which is also called the basis difference. If the futures price is greater than the spot price, we call it the futures premium; If the futures price is less than the spot price, we call it the futures discount. According to the futures delivery system, on the futures delivery date, the futures price should be equal to the spot price.&lt;br /&gt;&lt;br /&gt;Regardless of the premium or discount, due to the constraints of the futures delivery system, the futures price on the delivery date should be equal to the spot price in theory. As the delivery date approaches, both the spot price and the futures price will tend to be consistent. One is the return of futures to spot, and the other is the return of spot to futures.&lt;br /&gt;&lt;br /&gt;According to the above principle, we can use inventory and basis difference to determine future futures prices at the same time. If the inventory of a commodity is low, and if the futures price is much lower than the spot price, we can judge that the demand of the spot market is greater than the supply, and the probability of the spot price increasing in the future is large; Also due to the futures delivery system, as the delivery date approaches, the futures price will rise, and it will be equal to the spot price. The probability of futures price increasing is greater in the future.&lt;br /&gt;&lt;br /&gt;Finally, we judge the probable direction of the future price through the inventory and basis difference, but there is no accurate point of buying and selling, so we need to cooperate with technical analysis to give a clear signal of entry and exit. The structure of the whole fundamental analysis is: low inventory + deep discount + technical analysis long position signal = go long; High inventory + substantial premium + technical analysis short position signal = go short.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.2 Turtle trading rules&lt;/b&gt;&lt;br /&gt;When it comes to trading strategies, we have to talk about the representative turtle trading rules. The turtle trading rule comes from the most famous experiment in the history of trading. Richard Dennis, a commodity speculator, wants to know whether great traders are born or trained. To this end, in 1983, he recruited 13 people and taught them the basic concepts of futures trading, as well as his own trading methods and principles. These students were called &amp;quot;turtles&amp;quot;.&lt;br /&gt;&lt;br /&gt;In the following four years, the Turtles achieved an average annual compound interest of 80%. Dennis proved that with a simple system and rules, people with little or no trading experience can become excellent traders. However, some turtles sell turtle trading rules on the website for profit. In order to prevent this behavior, two original turtles, Curtis Firth and Arthur Maddock, decided to make the turtle trading rules available to the public free of charge on the website.&lt;br /&gt;&lt;br /&gt;After the truth came out, people found that the Turtle trading rules adopted the optimized Donchian channel and used ATR indicators for position management. After decades of historical tests, it has become an easy trading method for ordinary retail investors to make profits. It still works today in some varieties.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Turtle core principles&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- Mastering advantages: find a trading strategy with positive expectations, because in the long run, it can create positive returns.&lt;br /&gt;- Manage risk: control risk and hold your position, otherwise you may not wait for a day to make profits.&lt;br /&gt;- Perseverance: Only by unswervingly implementing your strategy, can you truly achieve systematic results.&lt;br /&gt;- Simple and clear: In the long run, simple systems have more vitality than complex systems.&lt;br /&gt;&lt;br /&gt;So next, let&amp;#39;s see what the Turtle trading rules say.&lt;br /&gt;1. Market - what to buy and sell, essentially in which markets to trade. Turtles are futures traders. They choose the markets with large trading volume and high liquidity only. Because choosing the markets with inactive trading will increase the extra slippage of entry and exit, and will also miss many opportunities of trend.&lt;br /&gt;2. Position size - how much to buy or sell is a very important part of the whole strategy, which is usually ignored or wrongly treated by most people. The Turtle trading rule adopts ATR, that is, the average real volatility index, to calculate the open position, increase position signal and stop loss signal. This is a very ingenious design. The original intention is to adjust the size of the position through the absolute volatility of the market. When the market volatility is strong, reduce the position, and when the market volatility is weak, increase the position. It first defines a unit whose formula is: (total assets * 1%)/ATR. The initial position is 1 unit. Even if the decline of the variety on that day reaches the level of ATR, the loss on that day can be controlled within 1% of the total asset. If the price rises by 0.5 unit, the long position will increase their positions by 1 unit, up to 4 units.&lt;br /&gt;3. Market entry - Turtle&amp;#39;s market entry is based on the Donchian channel. When the price rises above the highest price of the first 20 or 55 K lines, it will enter the market to go long. When the price falls below the lowest price of the first 20 or 55 K lines, it will enter the market to go short. When the signal appears, enter the market for trading, without waiting for the close or the next K-line.&lt;br /&gt;4. Stop loss - In the long run, transactions that do not stop loss will not succeed, but most traders are holding loss positions and trying to take chances to hope that the market will turn over. Turtle rules stipulate when to withdraw from the loss position strictly. If you hold long position orders and the price drops by 2 units, the long position is closed with a stop loss. If you hold a short position order and the price rises by 2 units, the short position will be closed with a stop loss.&lt;br /&gt;5. Stop profit - In Turtle rules, stop profit means losing a lot of floating profits, which is also an unacceptable part for many traders. If you currently hold long position orders and the price falls below the track of the Donchian channel of ten days, close all long orders; If the current short position order is held and the price rises above the track of the Donchian channel of ten days, close all short positions.&lt;br /&gt;&lt;br /&gt;Thus we can see that although the Turtle trading rules look very simple, in fact it has formed a real sense of the prototype of the trading system. It covers all aspects of a complete trading system, leaving no room for traders to make subjective imaginative decisions, which just makes the advantages of programmed operation of the system play, including: entry and exit rules, fund management and risk control, etc.&lt;br /&gt;&lt;br /&gt;The biggest advantage of the turtle trading method is to help us establish a set of effective trading methods. It is a combination of batch opening, dynamic stop profits and stop loss, and the trend following strategy of the market, especially the use of ATR value and the concept of position management, which is very worth learning. Of course, it also has a common problem with trend tracking strategy, that is, floating profit and taking back. It is likely that all the floating profits gained from buying the winners will be taken out due to the following wave of sharp falls. It is very strong in the general trend, and not as good as expected in the volatile market.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;3. Develop futures CTA strategy in practice&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;3.1 Development of CTA trend strategy based on MyLanguage&lt;/b&gt;&lt;br /&gt;At the end of the last century, a very amazing trading method began to prevail in the field of financial investment in the United States. After thousands of people&amp;#39;s practice, people found that this method has effectiveness and great practical value. At the same time, it has been recognized by many investment experts and professional traders. Until now, it can be applied to almost all financial investment fields perfectly, whether foreign exchange, gold, stocks, futures, crude oil, or index and bond, which is chaos operation method.&lt;br /&gt;&lt;br /&gt;The word chaos refers to the description of the chaotic state of the universe originally. Its idea is that the result is inevitable, but because the existing knowledge cannot calculate the result, because the calculation itself is also changing the result, the maximum or minimum result may appear at last, but there is no inevitable result. This is very similar to the trading market. Participants also change the market when they analyze the market and buy and sell. The market has eternal variability. When the participants understand the new form of the market, the market also understands that it is recognized by the participants, so the variation occurs. And it will tend to change in the unknown direction of the participants. It has enough wisdom to prevent the participants from catching its change rules, that is, the market is not stable, and the understanding of the past of the market cannot represent the future.&lt;br /&gt;&lt;br /&gt;The chaos operation method is a complete set of investment ideas, trading strategies and entry and exit signals, invented by Bill Williams. At present, many investors in the world adopt chaos operation to participate in market transactions. Because the development of China&amp;#39;s financial market lags behind, and chaos theory is also a relatively new idea, there are few people studying chaos operation methods in China. Since chaos operation method is a trading strategy with high universality and can be applied to almost all financial investment fields, including stocks, bonds, futures, foreign exchange, and digital currency, this course uses a simplified version of chaos strategy as a starting point to improve your investment interest and income.&lt;br /&gt;&lt;br /&gt;As the name implies, the theoretical basis of chaos operation method is chaos theory, which was proposed by meteorologist Edward Lorenz. It was one of the greatest scientific discoveries at the end of the 20th century. He put forward the famous &amp;quot;butterfly effect&amp;quot;. Bill Williams applied chaos theory to the field of financial investment creatively, combined with fractal geometry, nonlinear dynamics and other disciplines, and created a series of very effective technical analysis indicators.&lt;br /&gt;&lt;br /&gt;The entire Chaos operation method is composed of five major dimensions (technical indicators):&lt;br /&gt;&lt;br /&gt;- Alligator&lt;br /&gt;&lt;br /&gt;- The Fractal&lt;br /&gt;&lt;br /&gt;- The Momentum&lt;br /&gt;&lt;br /&gt;- Acceleration&lt;br /&gt;&lt;br /&gt;- The Balance Line&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150378
" title="https://stocksharp.com/file/150378
"&gt;https://stocksharp.com/file/150378
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s look at the above chart. The Alligator is a set of equilibrium lines using fractal geometry and nonlinear dynamics. Its essence is to extend the exponentially weighted moving average, which is a kind of mean line, but its calculation method is slightly more complicated than the ordinary mean line. Next, let&amp;#39;s look at how to define the Alligator in MyLanguage:&lt;br /&gt;```&lt;br /&gt;// Parameters&lt;br /&gt;N1:=11;&lt;br /&gt;N2:=21;&lt;br /&gt;&lt;br /&gt;// Defining the price median&lt;br /&gt;N3:=N1+N2;&lt;br /&gt;N4:=N2+N3;&lt;br /&gt;HL:=(H+L)/2;&lt;br /&gt;&lt;br /&gt;// Alligator&lt;br /&gt;Y^^SMA(REF(HL,N3),N4,1);&lt;br /&gt;R:=SMA(REF(HL,N2),N3,1);&lt;br /&gt;G:=SMA(REF(HL,N1),N2,1);&lt;br /&gt;```&lt;br /&gt;First, we define 2 external parameters N1 and N2, and then calculate the average HL of the highest price and the lowest price according to the external parameters, and then calculate the average HL with different parameters. For teeth, it is the average of the middle period of the midline, and the jaw is the average of the large period of the midline. In this strategy, we use the jaw.&lt;br /&gt;&lt;br /&gt;In the chaos operation method, a fractal concept is defined vividly. We can make an analogy: open the palm of the hand, with the fingers facing up, the middle finger is the upper fractal, the left little finger and the ring finger, and the right index finger and thumb respectively, represent the K-line with no record high. A basic fractal is composed of these five K-lines. Then you can define fractal with the following code:&lt;br /&gt;```&lt;br /&gt;// Fractal&lt;br /&gt;TOP_N:=BARSLAST(REF(H,2)=HHV(H,5))+2;&lt;br /&gt;BOTTOM_N:=BARSLAST(REF(L,2)=LLV(L,5))+2;&lt;br /&gt;&lt;br /&gt;TOP:=REF(H,TOP_N);&lt;br /&gt;BOTTOM:=REF(L,BOTTOM_N);&lt;br /&gt;&lt;br /&gt;MAX_YRG^^MAX(MAX(Y,R),G); &lt;br /&gt;MIN_YRG^^MIN(MIN(Y,R),G); &lt;br /&gt;&lt;br /&gt;TOP_FRACTAL^^VALUEWHEN(H&amp;gt;=MAX_YRG,TOP);&lt;br /&gt;BOTTOM_FRACTAL^^VALUEWHEN(L&amp;lt;=MIN_YRG,BOTTOM);&lt;br /&gt;```&lt;br /&gt;After calculating the alligator and fractal, we can write a simple chaos operation strategy based on these two conditions, and use a group of exponentially weighted moving average lines as the benchmark price for calculating the alligator and fractal index. Of course, the original chaotic operation strategy will be more complex. The code is as follows:&lt;br /&gt;```&lt;br /&gt;// If there are no current long position orders and the closing price rises above the upper fractal and the upper fractal is above the alligator, open a long position.&lt;br /&gt;BKVOL=0 AND C&amp;gt;=TOP_FRACTAL AND TOP_FRACTAL&amp;gt;MAX_YRG,BPK(1);&lt;br /&gt;// If there are no current short position orders and the closing price falls below the lower fractal and the lower fractal is below the alligator, open a short position.&lt;br /&gt;SKVOL=0 AND C&amp;lt;=BOTTOM_FRACTAL AND BOTTOM_FRACTAL&amp;lt;MIN_YRG,SPK(1);&lt;br /&gt;&lt;br /&gt;// Long positions are closed if the closing price falls below the jaws of the alligator.&lt;br /&gt;C&amp;lt;Y,SP(BKVOL);&lt;br /&gt;// Short positions are closed if the closing price rises above the jaws of the alligator.&lt;br /&gt;C&amp;gt;Y,BP(SKVOL);&lt;br /&gt;```&lt;br /&gt;For ease of understanding, I wrote the detailed comments into the code directly. We can simply list the trading logic of this strategy as follows:&lt;br /&gt;&lt;br /&gt;- Long opening position: if there are no long position orders at present, and the closing price rises below the upper fractal, and the upper fractal is above the alligator.&lt;br /&gt;- Short opening position: if there are no short position orders at present, and the closing price falls below the lower fractal, and the lower fractal is below the alligator.&lt;br /&gt;- Long closing position: if the closing price falls below the alligator chin.&lt;br /&gt;- Short closing position: if the closing price rises above the alligator chin.&lt;br /&gt;&lt;br /&gt;Next, let&amp;#39;s see what the results of this simple chaos operation strategy backtest actually look like. In order to make the backtest more close to the real market environment, the commission is set to twice the exchange rate, and the opening and closing positions are subject to a sliding point of two jumps each. The backtest data type is the rebar index, and the trading type is the rebar main force continuous, with a fixed 1 lot opening position. The following is the preliminary backtest performance report at the 1-hour level.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150379
" title="https://stocksharp.com/file/150379
"&gt;https://stocksharp.com/file/150379
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From the capital curve and backtest performance data, the strategy performed well, and the overall capital curve was steadily upward. However, since the end of 2016, the market characteristics of rebar varieties have changed, from the unilateral trend of high volatility to the broad volatility trend. From the perspective of capital curve, the profit from 2017 to now is obviously weak.&lt;br /&gt;&lt;br /&gt;In a word, the essence of chaos operation method is to find a turning point, without caring about how the market goes or whether it is true or false breakout. If it breaks through the fractal, it will enter the market directly. Never try to predict the market, but be an observer and follower.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3.2 Development of CTA arbitrage strategy based on JavaScript language&lt;/b&gt;&lt;br /&gt;George Soros put forward an important proposition in &amp;quot;The Alchemy of Finance&amp;quot; written in 1987: I believe the market prices are always wrong in the sense that they present a biased view of the future. He believed that the market efficiency hypothesis is only a theoretical hypothesis. In fact, market participants are not always rational, and at each time point, participants cannot completely obtain and objectively interpret all information. Moreover, even if it is the same information, everyone&amp;#39;s feedback is different. That is to say, the price itself already contains the wrong expectations of market participants, so in essence, the market price is always wrong. This may be the profit source of arbitrageurs.&lt;br /&gt;&lt;br /&gt;According to the above principles, we can know that in an ineffective futures market, the reason why the market impact on delivery contracts in different periods is not always synchronous, and the pricing is not completely effective. Then, based on the delivery contract price of the same transaction object in different periods, if there is a large price difference between the two prices, we can buy and sell futures contracts in different periods at the same time for cross-period arbitrage.&lt;br /&gt;&lt;br /&gt;Like commodity futures, digital currency also has a cross-period arbitrage contract portfolio. For example, in the OKEX exchange, there are: ETC current week, ETC next week, ETC quarter. For example, suppose that the price difference between the current week of ETC and the quarter of ETC remains around 5 for a long time. If the price difference reaches 7 one day, we expect that the price difference will return to 5 in the future. Then we can sell ETC that week and buy ETC quarter at the same time to go short the price difference, vice versa.&lt;br /&gt;&lt;br /&gt;Although this price difference exists, there are many uncertainties in manual arbitrage due to time-consuming manual operations, poor accuracy and the impact of price changes. The charm of quantitative arbitrage lies in capturing arbitrage opportunities through quantitative models and formulating arbitrage trading strategies, as well as placing trading orders automatically to exchanges through programmed algorithms, so as to capture opportunities quickly and accurately and make profits efficiently and stably.&lt;br /&gt;&lt;br /&gt;This course will teach you how to use the FMZ Quant Trading Platform and the ETC futures contract in the OKEX exchange to demonstrate how to capture the instantaneous arbitrage opportunities, seize the profits that can be seen every time, and hedge the risks that may be encountered in the digital currency trading with a simple arbitrage strategy.&lt;br /&gt;&lt;br /&gt;Create a cross-period arbitrage strategy for digital currency&lt;br /&gt;Difficulty: Normal&lt;br /&gt;&lt;br /&gt;Strategy environment&lt;br /&gt;&lt;br /&gt;- Transaction object: Ether Classic (ETC)&lt;br /&gt;- Spread data: ETC current week - ETC quarter (omit cointegration test)&lt;br /&gt;- Transaction period: 5 minutes&lt;br /&gt;- Transaction period: 5 minutes&lt;br /&gt;- Transaction type: cross period of the same type&lt;br /&gt;&lt;br /&gt;Strategy logic&lt;br /&gt;&lt;br /&gt;- Conditions for opening positions with going long the price difference: if the current account has no positions and the price difference is less than the lower bound of the ball, then go long the price difference. That is, buy opening positions ETC for the week, sell opening positions ETC for the quarter.&lt;br /&gt;- Conditions for opening positions with going short the price difference: if there is no position in the current account, and the price difference is greater than the upper bound of the ball, then go short the price difference. That is, sell opening positions ETC for the week, buy opening positions ETC for the quarter.&lt;br /&gt;- Conditions for closing positions with going long the price difference: if the current account holds going long orders of ETC in the current week and holds going short orders of ETC quarter, and the price difference is greater than the middle bound of the ball, then close long the price difference. That is, sell closing positions ETC for the week, buy closing positions ETC for the quarter.&lt;br /&gt;- Conditions for closing positions with going short the price difference: if the current account holds going short orders of ETC in the current week, and holds going long orders of ETC quarter, and the price difference is less than the middle bound of the ball, then close short the price difference. That is, buy closing positions ETC for the week, sell closing positions ETC for the quarter.&lt;br /&gt;&lt;br /&gt;The above is a simple logic description of the cross-period arbitrage strategy of digital currency. So how to implement our ideas in the program? We try to build the framework on the FMZ Quant Trading Platform.&lt;br /&gt;```&lt;br /&gt;function Data() {}  // Basic data function&lt;br /&gt;Data.prototype.mp = function () {}  // Position function&lt;br /&gt;Data.prototype.boll = function () {}  // Indicator function&lt;br /&gt;Data.prototype.trade = function () {}  // Order placement function&lt;br /&gt;Data.prototype.cancelOrders = function () {}  // Order withdrawal function&lt;br /&gt;Data.prototype.isEven = function () {}  // Processing single contract function&lt;br /&gt;Data.prototype.drawingChart = function () {}  // Drawing function&lt;br /&gt;&lt;br /&gt;function onTick() {&lt;br /&gt;    var data = new Data(tradeTypeA, tradeTypeB);  // Create a basic data object&lt;br /&gt;    var accountStocks = data.accountData.Stocks;  // Account balance&lt;br /&gt;    var boll = data.boll(dataLength, timeCycle);  // Calculate the technical indicators of boll&lt;br /&gt;    data.trade();  // Calculate trading conditions to place an order&lt;br /&gt;    data.cancelOrders();  // Cancel orders&lt;br /&gt;    data.drawingChart(boll);  // Drawing&lt;br /&gt;    data.isEven();  // Processing of holding individual contract&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//Entry function&lt;br /&gt;function main() {&lt;br /&gt;    while (true) {  // Enter the polling mode&lt;br /&gt;        onTick();  // Execute onTick function&lt;br /&gt;        Sleep(500);  // Sleep for 0.5 seconds&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;Imagine what our trading process is like in supervisory trading. There is no essential difference in system transactions. It is nothing more than acquiring data, calculating data, placing an order transaction, and processing after placing an order. The same is true in the program. First, the program will execute the main function in line 20, which is a convention. When the program completes the trading strategy preprocessing (if any), it will enter the infinite loop mode, that is, the polling mode. In the polling mode, the onTick function will be executed repeatedly.&lt;br /&gt;&lt;br /&gt;Then in the onTick function, it is our trading process in the subjective transaction: first, obtain the basic price data, then obtain the account balance, then calculate the index, then calculate the trading conditions and place the order, and finally the processing after placing the order, including order cancellation, drawing, and processing a single contract.&lt;br /&gt;&lt;br /&gt;The strategy framework can be easily set up according to the strategy idea and transaction process. The whole strategy can be simplified into three steps:&lt;br /&gt;&lt;br /&gt;- Pre-processing before transaction.&lt;br /&gt;- Get and calculate data.&lt;br /&gt;- Place an order and deal with it later.&lt;br /&gt;&lt;br /&gt;Next, we need to fill in the necessary detail code in the strategy framework according to the actual transaction process and transaction details.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;I. Pre-processing before transaction&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Declare the necessary global variables in the global scope.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- Declare a chart object for the configuration chart&lt;br /&gt;```&lt;br /&gt;var chart = {}&lt;br /&gt;```&lt;br /&gt;- Call Chart function and initialize the chart&lt;br /&gt;```&lt;br /&gt;var ObjChart = Chart ( chart )&lt;br /&gt;```&lt;br /&gt;- Declare an empty array to store price difference series&lt;br /&gt;```&lt;br /&gt;var bars = []&lt;br /&gt;```&lt;br /&gt;- Declare a record history data timestamp variable&lt;br /&gt;```&lt;br /&gt;var oldTime = 0&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;2. Configure the external parameters of the strategy.&lt;/b&gt;&lt;br /&gt;```&lt;br /&gt;var tradeTypeA = &amp;quot;this_week&amp;quot;; // Arbitrage A Contract&lt;br /&gt;var tradeTypeB = &amp;quot;quarter&amp;quot;; // Arbitrage B Contract&lt;br /&gt;var dataLength = 10; // Indicator period length&lt;br /&gt;var timeCycle = 1; // K-line period&lt;br /&gt;var name = &amp;quot;ETC&amp;quot;; // Currencies&lt;br /&gt;var unit = 1; // Order quantity&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;3. Define the data processing function&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- Basic data function: Data()&lt;br /&gt;Create a constructor, Data, and define its internal properties. Including: account data, position data, K-line data timestamp, buy/sell price of arbitrage A/B contract, and positive/negative arbitrage price difference.&lt;br /&gt;```&lt;br /&gt;function Data(tradeTypeA, tradeTypeB) { // Pass in arbitrage A contract and arbitrage B contract&lt;br /&gt;    this.accountData = _C(exchange.GetAccount); // Get account information&lt;br /&gt;    this.positionData = _C(exchange.GetPosition); // Get position information&lt;br /&gt;    var recordsData = _C(exchange.GetRecords); // Get K-line data&lt;br /&gt;    exchange.SetContractType(tradeTypeA); // Subscription arbitrage A contract&lt;br /&gt;    var depthDataA = _C(exchange.GetDepth); // Depth data of arbitrage A contract&lt;br /&gt;    exchange.SetContractType(tradeTypeB); // Subscription arbitrage B contract&lt;br /&gt;    var depthDataB = _C(exchange.GetDepth); // Depth data of arbitrage B contract&lt;br /&gt;    this.time = recordsData[recordsData.length - 1].Time; // Time of obtaining the latest data&lt;br /&gt;    this.askA = depthDataA.Asks[0].Price; // Sell one price of Arbitrage A contract&lt;br /&gt;    this.bidA = depthDataA.Bids[0].Price; // Buy one price of Arbitrage A contract&lt;br /&gt;    this.askB = depthDataB.Asks[0].Price; // Sell one price of Arbitrage B contract&lt;br /&gt;    this.bidB = depthDataB.Bids[0].Price; // Buy one price of Arbitrage B contract&lt;br /&gt;    // Positive arbitrage price differences (Sell one price of contract A - Buy one price of contract B)&lt;br /&gt;    this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;&lt;br /&gt;    // Negative arbitrage price differences (Buy one price of contract A - Sell one price of contract B)&lt;br /&gt;    this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;- Get the position function: mp ( )&lt;br /&gt;Traverse the entire position array and return the position quantity of the specified contract and direction. If not, return false.&lt;br /&gt;```&lt;br /&gt;Data.prototype.mp = function (tradeType, type) {&lt;br /&gt;    var positionData = this.positionData; // Get position information&lt;br /&gt;    for (var i = 0; i &amp;lt; positionData.length; i++) {&lt;br /&gt;        if (positionData[i].ContractType == tradeType) {&lt;br /&gt;            if (positionData[i].Type == type) {&lt;br /&gt;                if (positionData[i].Amount &amp;gt; 0) {&lt;br /&gt;                    return positionData[i].Amount;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    return false;&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;- K-line and indicator function: boll()&lt;br /&gt;A new K-line sequence is synthesized according to the positive arbitrage/negative arbitrage price difference data. The data of upper track, middle track and lower track calculated by the boll indicator are returned.&lt;br /&gt;```&lt;br /&gt;Data.prototype.boll = function (num, timeCycle) {&lt;br /&gt;    var self = {}; // Temporary objects&lt;br /&gt;    // Median value of positive arbitrage price difference and negative arbitrage price difference&lt;br /&gt;    self.Close = (this.basb + this.sabb) / 2;&lt;br /&gt;    if (this.timeA == this.timeB) {&lt;br /&gt;        self.Time = this.time;&lt;br /&gt;    } // Compare two depth data timestamps&lt;br /&gt;    if (this.time - oldTime &amp;gt; timeCycle * 60000) {&lt;br /&gt;        bars.push(self);&lt;br /&gt;        oldTime = this.time;&lt;br /&gt;    } // Pass in the price difference data object into the K-line array according to the specified time period&lt;br /&gt;    if (bars.length &amp;gt; num * 2) {&lt;br /&gt;        bars.shift(); // Control the length of the K-line array&lt;br /&gt;    } else {&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;    var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the talib library&lt;br /&gt;    return {&lt;br /&gt;        up: boll[0][boll[0].length - 1], // boll indicator upper track&lt;br /&gt;        middle: boll[1][boll[1].length - 1], // boll indicator middle track&lt;br /&gt;        down: boll[2][boll[2].length - 1] // boll indicator down track&lt;br /&gt;    } // Return a processed boll indicator data&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;- Order function: trade()&lt;br /&gt;Pass in the order contract name and order type, then place the order with consideration, and return the result after placing the order. Since it is necessary to place two orders in different directions at the same time, the buy/sell one price is converted within the function according to the contract name of the order.&lt;br /&gt;```&lt;br /&gt;Data.prototype.trade = function (tradeType, type) {&lt;br /&gt;    exchange.SetContractType(tradeType); // Resubscribe to a contract before placing an order&lt;br /&gt;    var askPrice, bidPrice;&lt;br /&gt;    if (tradeType == tradeTypeA) { // If the order is placed in contract A&lt;br /&gt;        askPrice = this.askA; // set askPrice&lt;br /&gt;        bidPrice = this.bidA; // set bidPrice&lt;br /&gt;    } else if (tradeType == tradeTypeB) { // If the order is placed in contract B&lt;br /&gt;        askPrice = this.askB; // set askPrice&lt;br /&gt;        bidPrice = this.bidB; // set bidPrice&lt;br /&gt;    }&lt;br /&gt;    switch (type) { // Match order placement mode&lt;br /&gt;        case &amp;quot;buy&amp;quot;:&lt;br /&gt;            exchange.SetDirection(type); // Set order placement mode&lt;br /&gt;            return exchange.Buy(askPrice, unit);&lt;br /&gt;        case &amp;quot;sell&amp;quot;:&lt;br /&gt;            exchange.SetDirection(type); // Set order placement mode&lt;br /&gt;            return exchange.Sell(bidPrice, unit);&lt;br /&gt;        case &amp;quot;closebuy&amp;quot;:&lt;br /&gt;            exchange.SetDirection(type); // Set order placement mode&lt;br /&gt;            return exchange.Sell(bidPrice, unit);&lt;br /&gt;        case &amp;quot;closesell&amp;quot;:&lt;br /&gt;            exchange.SetDirection(type); // Set order placement mode&lt;br /&gt;            return exchange.Buy(askPrice, unit);&lt;br /&gt;        default:&lt;br /&gt;            return false;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;- Cancel Order Function: cancelOrders()&lt;br /&gt;Get an array of all outstanding orders and cancel them one by one. In addition, false is returned if there is an unfilled order, and true is returned if there is no unfilled order.&lt;br /&gt;```&lt;br /&gt;Data.prototype.cancelOrders = function () {&lt;br /&gt;    Sleep(500); // Delay before cancellation, because some exchanges, you know what I mean&lt;br /&gt;    var orders = _C(exchange.GetOrders); // Get an array of unfilled orders&lt;br /&gt;    if (orders.length &amp;gt; 0) { // If there are unfilled orders&lt;br /&gt;        for (var i = 0; i &amp;lt; orders.length; i++) { // Iterate through the array of unfilled orders&lt;br /&gt;            exchange.CancelOrder(orders[i].Id); // Cancel unfilled orders one by one&lt;br /&gt;            Sleep(500); // Delay 0.5 seconds&lt;br /&gt;        }&lt;br /&gt;        return false; // Return false if an unfilled order is cancelled&lt;br /&gt;    }&lt;br /&gt;    return true; // Return true if there are no unfilled orders&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;- Handle holding a single contract: isEven()&lt;br /&gt;In the case of a single leg in the arbitrage transaction, we will simply close all positions. Of course, it can also be changed to the tracking method.&lt;br /&gt;```&lt;br /&gt;Data.prototype.isEven = function () {&lt;br /&gt;    var positionData = this.positionData; // Get position information&lt;br /&gt;    var type = null; // Switch position direction&lt;br /&gt;    // If the remaining 2 of the position array length is not equal to 0 or the position array length is not equal to 2&lt;br /&gt;    if (positionData.length % 2 != 0 || positionData.length != 2) {&lt;br /&gt;        for (var i = 0; i &amp;lt; positionData.length; i++) { // Iterate through the position array&lt;br /&gt;            if (positionData[i].Type == 0) { // If it is a long order&lt;br /&gt;                type = 10; // Set order parameters&lt;br /&gt;            } else if (positionData[i].Type == 1) { // If it is a short order&lt;br /&gt;                type = -10; // Set order parameters&lt;br /&gt;            }&lt;br /&gt;            // Close all positions&lt;br /&gt;            this.trade(positionData[i].ContractType, type, positionData[i].Amount);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;- Drawing function: drawingChart ( )&lt;br /&gt;Call ObjChart Add () method, draw the necessary market data and indicator data in the chart: upper track, middle track, lower track, positive/negative arbitrage price difference.&lt;br /&gt;```&lt;br /&gt;Data.prototype.drawingChart = function (boll) {&lt;br /&gt;    var nowTime = new Date().getTime();&lt;br /&gt;    ObjChart.add([0, [nowTime, boll.up]]);&lt;br /&gt;    ObjChart.add([1, [nowTime, boll.middle]]);&lt;br /&gt;    ObjChart.add([2, [nowTime, boll.down]]);&lt;br /&gt;    ObjChart.add([3, [nowTime, this.basb]]);&lt;br /&gt;    ObjChart.add([4, [nowTime, this.sabb]]);&lt;br /&gt;    ObjChart.update(chart);&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;4. In the entry function main(), execute the pre-transaction pre-processing code, which will only run once after the program is started, including:&lt;/b&gt;&lt;br /&gt;- ```SetErrorFilter ( )``` to filter the unimportant information in the console&lt;br /&gt;- ```exchange.IO ( )``` to set the digital currency to be traded&lt;br /&gt;- ```ObjChart.reset ( )``` to clear the previous chart drawn before starting the program&lt;br /&gt;- ```LogProfitReset ( )``` to clear the status bar information before starting the program&lt;br /&gt;&lt;br /&gt;After the above pre-transaction pre-processing is defined, the next step is to enter the polling mode and execute the onTick() function repeatedly. It also sets the sleep time for Sleep () polling, because the API of some digital currency exchanges has built-in access limit for a certain period of time.&lt;br /&gt;```&lt;br /&gt;function main() {&lt;br /&gt;    // Filter the unimportant information in the console&lt;br /&gt;    SetErrorFilter(&amp;quot;429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP&amp;quot;);&lt;br /&gt;    exchange.IO(&amp;quot;currency&amp;quot;, name + &amp;#39;_USDT&amp;#39;); // Set the digital currency to be traded&lt;br /&gt;    ObjChart.reset(); // Clear the previous chart drawn before starting the program&lt;br /&gt;    LogProfitReset(); // Clear the status bar information before starting the program&lt;br /&gt;    while (true) { // Enter the polling mode&lt;br /&gt;        onTick(); // Execute onTick function&lt;br /&gt;        Sleep(500); // Sleep for 0.5 seconds&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;II. Get and calculate data&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. Obtain basic data object, account balance, and boll indicator data for use in the trading logic.&lt;br /&gt;```&lt;br /&gt;function onTick() {&lt;br /&gt;    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object&lt;br /&gt;    var accountStocks = data.accountData.Stocks; // Account balance&lt;br /&gt;    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data&lt;br /&gt;    if (!boll) return; // Return if there is no boll data&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;III. Place an order and handle the follow-up&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. Execute the buying and selling operation according to the above strategic logic. First, judge whether the price and indicator conditions are valid, then judge whether the position conditions are valid, and finally execute the trade () order function.&lt;br /&gt;```&lt;br /&gt;// Explanation of the price difference&lt;br /&gt;// basb = (Sell one price of contract A - Buy one price of contract B)&lt;br /&gt;// sabb = (Buy one price of contract A - Sell one price of contract B)&lt;br /&gt;if (data.sabb &amp;gt; boll.middle &amp;amp;&amp;amp; data.sabb &amp;lt; boll.up) { // If sabb is higher than the middle track&lt;br /&gt;    if (data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order&lt;br /&gt;        data.trade(tradeTypeA, &amp;quot;closebuy&amp;quot;); // Contract A closes long position&lt;br /&gt;    }&lt;br /&gt;    if (data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order&lt;br /&gt;        data.trade(tradeTypeB, &amp;quot;closesell&amp;quot;); // Contract B closes short position&lt;br /&gt;    }&lt;br /&gt;} else if (data.basb &amp;lt; boll.middle &amp;amp;&amp;amp; data.basb &amp;gt; boll.down) { // If basb is lower than the middle track&lt;br /&gt;    if (data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order&lt;br /&gt;        data.trade(tradeTypeA, &amp;quot;closesell&amp;quot;); // Contract A closes short position&lt;br /&gt;    }&lt;br /&gt;    if (data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order&lt;br /&gt;        data.trade(tradeTypeB, &amp;quot;closebuy&amp;quot;); // Contract B closes long position&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;if (accountStocks * Math.max(data.askA, data.askB) &amp;gt; 1) { // If there is balance in the account&lt;br /&gt;    if (data.basb &amp;lt; boll.down) { // If basb price difference is lower than the down track&lt;br /&gt;        if (!data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order&lt;br /&gt;            data.trade(tradeTypeA, &amp;quot;buy&amp;quot;); // Contract A opens long position&lt;br /&gt;        }&lt;br /&gt;        if (!data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order&lt;br /&gt;            data.trade(tradeTypeB, &amp;quot;sell&amp;quot;); // Contract B opens short position&lt;br /&gt;        }&lt;br /&gt;    } else if (data.sabb &amp;gt; boll.up) { // If sabb price difference is higher than the upper track&lt;br /&gt;        if (!data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order&lt;br /&gt;            data.trade(tradeTypeA, &amp;quot;sell&amp;quot;); // Contract A opens short position&lt;br /&gt;        }&lt;br /&gt;        if (!data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order&lt;br /&gt;            data.trade(tradeTypeB, &amp;quot;buy&amp;quot;); // Contract B opens long position&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;2. After the order is placed, it is necessary to deal with the abnormal situations such as the unsettled order and the holding of a single contract. And draw the chart.&lt;br /&gt;```&lt;br /&gt;data.cancelOrders(); // cancel orders&lt;br /&gt;data.drawingChart(boll); // drawing&lt;br /&gt;data.isEven(); // Handle holding individual contracts&lt;br /&gt;```&lt;br /&gt;As above, we have created a simple cross-period arbitrage strategy of digital currency completely through more than 200 lines code. The complete code is as follows:&lt;br /&gt;```&lt;br /&gt;// Global variable&lt;br /&gt;// Declare a chart object for the configuration chart&lt;br /&gt;var chart = {&lt;br /&gt;    __isStock: true,&lt;br /&gt;    tooltip: {&lt;br /&gt;        xDateFormat: &amp;#39;%Y-%m-%d %H:%M:%S, %A&amp;#39;&lt;br /&gt;    },&lt;br /&gt;    title: {&lt;br /&gt;        text: &amp;#39;transaction profit and loss curve (detailed)&amp;#39;&lt;br /&gt;    },&lt;br /&gt;    rangeSelector: {&lt;br /&gt;        buttons: [{&lt;br /&gt;            type: &amp;#39;hour&amp;#39;,&lt;br /&gt;            count: 1,&lt;br /&gt;            text: &amp;#39;1h&amp;#39;&lt;br /&gt;        }, {&lt;br /&gt;            type: &amp;#39;hour&amp;#39;,&lt;br /&gt;            count: 2,&lt;br /&gt;            text: &amp;#39;3h&amp;#39;&lt;br /&gt;        }, {&lt;br /&gt;            type: &amp;#39;hour&amp;#39;,&lt;br /&gt;            count: 8,&lt;br /&gt;            text: &amp;#39;8h&amp;#39;&lt;br /&gt;        }, {&lt;br /&gt;            type: &amp;#39;all&amp;#39;,&lt;br /&gt;            text: &amp;#39;All&amp;#39;&lt;br /&gt;        }],&lt;br /&gt;        selected: 0,&lt;br /&gt;        inputEnabled: false&lt;br /&gt;    },&lt;br /&gt;    xAxis: {&lt;br /&gt;        type: &amp;#39;datetime&amp;#39;&lt;br /&gt;    },&lt;br /&gt;    yAxis: {&lt;br /&gt;        title: {&lt;br /&gt;            text: &amp;#39;price difference&amp;#39;&lt;br /&gt;        },&lt;br /&gt;        opposite: false,&lt;br /&gt;    },&lt;br /&gt;    series: [{&lt;br /&gt;        name: &amp;quot;upper track&amp;quot;,&lt;br /&gt;        id: &amp;quot;line1,up&amp;quot;,&lt;br /&gt;        data: []&lt;br /&gt;    }, {&lt;br /&gt;        name: &amp;quot;middle track&amp;quot;,&lt;br /&gt;        id: &amp;quot;line2,middle&amp;quot;,&lt;br /&gt;        data: []&lt;br /&gt;    }, {&lt;br /&gt;        name: &amp;quot;down track&amp;quot;,&lt;br /&gt;        id: &amp;quot;line3,down&amp;quot;,&lt;br /&gt;        data: []&lt;br /&gt;    }, {&lt;br /&gt;        name: &amp;quot;basb&amp;quot;,&lt;br /&gt;        id: &amp;quot;line4,basb&amp;quot;,&lt;br /&gt;        data: []&lt;br /&gt;    }, {&lt;br /&gt;        name: &amp;quot;sabb&amp;quot;,&lt;br /&gt;        id: &amp;quot;line5,sabb&amp;quot;,&lt;br /&gt;        data: []&lt;br /&gt;    }]&lt;br /&gt;};&lt;br /&gt;var ObjChart = Chart(chart); // Drawing object&lt;br /&gt;var bars = []; // Storage price difference series&lt;br /&gt;var oldTime = 0; // Record historical data timestamp&lt;br /&gt;&lt;br /&gt;// Parameters&lt;br /&gt;var tradeTypeA = &amp;quot;this_week&amp;quot;; // Arbitrage A contract&lt;br /&gt;var tradeTypeB = &amp;quot;quarter&amp;quot;; // Arbitrage B contract&lt;br /&gt;var dataLength = 10; // Indicator period length&lt;br /&gt;var timeCycle = 1; // K-line period&lt;br /&gt;var name = &amp;quot;ETC&amp;quot;; // Currencies&lt;br /&gt;var unit = 1; // Order quantity&lt;br /&gt;&lt;br /&gt;// basic data&lt;br /&gt;function Data(tradeTypeA, tradeTypeB) { // Pass in arbitrage A contract and arbitrage B contract&lt;br /&gt;    this.accountData = _C(exchange.GetAccount); // Get account information&lt;br /&gt;    this.positionData = _C(exchange.GetPosition); // Get position information&lt;br /&gt;    var recordsData = _C(exchange.GetRecords); // Get K-line data&lt;br /&gt;    exchange.SetContractType(tradeTypeA); // Subscribe to arbitrage A contract&lt;br /&gt;    var depthDataA = _C(exchange.GetDepth); // Arbitrage A contract depth data&lt;br /&gt;    exchange.SetContractType(tradeTypeB); // Subscribe to arbitrage B contract&lt;br /&gt;    var depthDataB = _C(exchange.GetDepth); // Arbitrage B contract depth data&lt;br /&gt;    this.time = recordsData[recordsData.length - 1].Time; // Time to get the latest data&lt;br /&gt;    this.askA = depthDataA.Asks[0].Price; // Sell one price of arbitrage A contract&lt;br /&gt;    this.bidA = depthDataA.Bids[0].Price; // Buy one price of arbitrage A contract&lt;br /&gt;    this.askB = depthDataB.Asks[0].Price; // Sell one price of arbitrage B contract&lt;br /&gt;    this.bidB = depthDataB.Bids[0].Price; // Buy one price of arbitrage B contract&lt;br /&gt;    // Positive arbitrage price difference (Sell one price of contract A - Buy one price of contract B)&lt;br /&gt;    this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;&lt;br /&gt;    // Negative arbitrage price difference (Buy one price of contract A - Sell one price of contract B)&lt;br /&gt;    this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Get position&lt;br /&gt;Data.prototype.mp = function (tradeType, type) {&lt;br /&gt;    var positionData = this.positionData; // Get position information&lt;br /&gt;    for (var i = 0; i &amp;lt; positionData.length; i++) {&lt;br /&gt;        if (positionData[i].ContractType == tradeType) {&lt;br /&gt;            if (positionData[i].Type == type) {&lt;br /&gt;                if (positionData[i].Amount &amp;gt; 0) {&lt;br /&gt;                    return positionData[i].Amount;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    return false;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Synthesis of new K-line data and boll indicator data&lt;br /&gt;Data.prototype.boll = function (num, timeCycle) {&lt;br /&gt;    var self = {}; // Temporary objects&lt;br /&gt;    // Median value of between positive arbitrage price difference and negative arbitrage price difference&lt;br /&gt;    self.Close = (this.basb + this.sabb) / 2;&lt;br /&gt;    if (this.timeA == this.timeB) {&lt;br /&gt;        self.Time = this.time;&lt;br /&gt;    } // Compare two depth data timestamps&lt;br /&gt;    if (this.time - oldTime &amp;gt; timeCycle * 60000) {&lt;br /&gt;        bars.push(self);&lt;br /&gt;        oldTime = this.time;&lt;br /&gt;    } // Pass in the price difference data object into the K-line array according to the specified time period&lt;br /&gt;    if (bars.length &amp;gt; num * 2) {&lt;br /&gt;        bars.shift(); // Control the length of the K-line array&lt;br /&gt;    } else {&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;    var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the talib library&lt;br /&gt;    return {&lt;br /&gt;        up: boll[0][boll[0].length - 1], // boll indicator upper track&lt;br /&gt;        middle: boll[1][boll[1].length - 1], // boll indicator middle track&lt;br /&gt;        down: boll[2][boll[2].length - 1] // boll indicator down track&lt;br /&gt;    } // Return a processed boll indicator data&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Place an order&lt;br /&gt;Data.prototype.trade = function (tradeType, type) {&lt;br /&gt;    exchange.SetContractType(tradeType); // Resubscribe to a contract before placing an order&lt;br /&gt;    var askPrice, bidPrice;&lt;br /&gt;    if (tradeType == tradeTypeA) { // If the order is placed in contract A&lt;br /&gt;        askPrice = this.askA; // Set askPrice&lt;br /&gt;        bidPrice = this.bidA; // Set bidPrice&lt;br /&gt;    } else if (tradeType == tradeTypeB) { // If the order is placed in contract B&lt;br /&gt;        askPrice = this.askB; // Set askPrice&lt;br /&gt;        bidPrice = this.bidB; // Set bidPrice&lt;br /&gt;    }&lt;br /&gt;    switch (type) { // Match order placement mode&lt;br /&gt;        case &amp;quot;buy&amp;quot;:&lt;br /&gt;            exchange.SetDirection(type); // Set order placement mode&lt;br /&gt;            return exchange.Buy(askPrice, unit);&lt;br /&gt;        case &amp;quot;sell&amp;quot;:&lt;br /&gt;            exchange.SetDirection(type); // Set order placement mode&lt;br /&gt;            return exchange.Sell(bidPrice, unit);&lt;br /&gt;        case &amp;quot;closebuy&amp;quot;:&lt;br /&gt;            exchange.SetDirection(type); // Set order placement mode&lt;br /&gt;            return exchange.Sell(bidPrice, unit);&lt;br /&gt;        case &amp;quot;closesell&amp;quot;:&lt;br /&gt;            exchange.SetDirection(type); // Set order placement mode&lt;br /&gt;            return exchange.Buy(askPrice, unit);&lt;br /&gt;        default:&lt;br /&gt;            return false;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Cancel orders&lt;br /&gt;Data.prototype.cancelOrders = function () {&lt;br /&gt;    Sleep(500); // Delay before cancellation, because some exchanges, you know what I mean&lt;br /&gt;    var orders = _C(exchange.GetOrders); // Get an array of unfilled orders&lt;br /&gt;    if (orders.length &amp;gt; 0) { // If there are unfilled orders&lt;br /&gt;        for (var i = 0; i &amp;lt; orders.length; i++) { // Iterate through the array of unfilled orders&lt;br /&gt;            exchange.CancelOrder(orders[i].Id); // Cancel unfilled orders one by one&lt;br /&gt;            Sleep(500); // Sleep for 0.5 seconds&lt;br /&gt;        }&lt;br /&gt;        return false; // Return false if an unfilled order is cancelled&lt;br /&gt;    }&lt;br /&gt;    return true; // Return true if there are no unfilled orders&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Handle holding individual contracts&lt;br /&gt;Data.prototype.isEven = function () {&lt;br /&gt;    var positionData = this.positionData; // Get position information&lt;br /&gt;    var type = null; // Switch position direction&lt;br /&gt;    // If the remaining 2 of the position array length is not equal to 0 or the position array length is not equal to 2&lt;br /&gt;    if (positionData.length % 2 != 0 || positionData.length != 2) {&lt;br /&gt;        for (var i = 0; i &amp;lt; positionData.length; i++) { // Iterate through the position array&lt;br /&gt;            if (positionData[i].Type == 0) { // If it is a long order&lt;br /&gt;                type = 10; // Set order parameters&lt;br /&gt;            } else if (positionData[i].Type == 1) { // If it is a short order&lt;br /&gt;                type = -10; // Set order parameters&lt;br /&gt;            }&lt;br /&gt;            // Close all positions&lt;br /&gt;            this.trade(positionData[i].ContractType, type, positionData[i].Amount);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Drawing&lt;br /&gt;Data.prototype.drawingChart = function (boll) {&lt;br /&gt;    var nowTime = new Date().getTime();&lt;br /&gt;    ObjChart.add([0, [nowTime, boll.up]]);&lt;br /&gt;    ObjChart.add([1, [nowTime, boll.middle]]);&lt;br /&gt;    ObjChart.add([2, [nowTime, boll.down]]);&lt;br /&gt;    ObjChart.add([3, [nowTime, this.basb]]);&lt;br /&gt;    ObjChart.add([4, [nowTime, this.sabb]]);&lt;br /&gt;    ObjChart.update(chart);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Trading conditions&lt;br /&gt;function onTick() {&lt;br /&gt;    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object&lt;br /&gt;    var accountStocks = data.accountData.Stocks; // Account balance&lt;br /&gt;    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data&lt;br /&gt;    if (!boll) return; // Return if there is no boll data&lt;br /&gt;    // Explanation of price difference&lt;br /&gt;    // basb = (Sell one price of contract A - Buy one price of contract B)&lt;br /&gt;    // sabb = (Buy one price of contract A - Sell one price of contract B)&lt;br /&gt;    if (data.sabb &amp;gt; boll.middle &amp;amp;&amp;amp; data.sabb &amp;lt; boll.up) { // If sabb is higher than the middle track&lt;br /&gt;        if (data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order&lt;br /&gt;            data.trade(tradeTypeA, &amp;quot;closebuy&amp;quot;); // Contract A closes long position&lt;br /&gt;        }&lt;br /&gt;        if (data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order&lt;br /&gt;            data.trade(tradeTypeB, &amp;quot;closesell&amp;quot;); // Contract B closes short position&lt;br /&gt;        }&lt;br /&gt;    } else if (data.basb &amp;lt; boll.middle &amp;amp;&amp;amp; data.basb &amp;gt; boll.down) { // If basb is lower than the middle track&lt;br /&gt;        if (data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order&lt;br /&gt;            data.trade(tradeTypeA, &amp;quot;closesell&amp;quot;); // Contract A closes short position&lt;br /&gt;        }&lt;br /&gt;        if (data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order&lt;br /&gt;            data.trade(tradeTypeB, &amp;quot;closebuy&amp;quot;); // Contract B closes long position&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    if (accountStocks * Math.max(data.askA, data.askB) &amp;gt; 1) { // If there is a balance in the account&lt;br /&gt;        if (data.basb &amp;lt; boll.down) { // If basb price difference is lower than the down track&lt;br /&gt;            if (!data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order&lt;br /&gt;                data.trade(tradeTypeA, &amp;quot;buy&amp;quot;); // Contract A opens long position&lt;br /&gt;            }&lt;br /&gt;            if (!data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order&lt;br /&gt;                data.trade(tradeTypeB, &amp;quot;sell&amp;quot;); // Contract B opens short position&lt;br /&gt;            }&lt;br /&gt;        } else if (data.sabb &amp;gt; boll.up) { // If sabb price difference is higher than the upper track&lt;br /&gt;            if (!data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order&lt;br /&gt;                data.trade(tradeTypeA, &amp;quot;sell&amp;quot;); // Contract A opens short position&lt;br /&gt;            }&lt;br /&gt;            if (!data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order&lt;br /&gt;                data.trade(tradeTypeB, &amp;quot;buy&amp;quot;); // Contract B opens long position&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    data.cancelOrders(); // Cancel orders&lt;br /&gt;    data.drawingChart(boll); // Drawing&lt;br /&gt;    data.isEven(); // Handle holding individual contracts&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Entry function&lt;br /&gt;function main() {&lt;br /&gt;    // Filter unimportant information in the console&lt;br /&gt;    SetErrorFilter(&amp;quot;429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP&amp;quot;);&lt;br /&gt;    exchange.IO(&amp;quot;currency&amp;quot;, name + &amp;#39;_USDT&amp;#39;); //Set the digital currency to be traded&lt;br /&gt;    ObjChart.reset(); // Clear the previous chart drawn before starting the program&lt;br /&gt;    LogProfitReset(); // Clear the status bar information before starting the program&lt;br /&gt;    while (true) { // Enter polling mode&lt;br /&gt;        onTick(); // Execute the onTick function&lt;br /&gt;        Sleep(500); // Sleep for 0.5 seconds&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;Arbitrage trading originated from the stock trading strategy of Morgan Stanley. Its idea is that the price difference of two highly correlated varieties conforms to the &amp;quot;popcorn process&amp;quot;, that is, the price difference keeps returning to the mean from a position that deviates from the historical mean, and then deviates again from the mean.&lt;br /&gt;&lt;br /&gt;Therefore, we can buy low and sell high on the price difference to gain profits. Then, according to the principle of standard deviation in statistics, the Bollinger band is formed by a middle track and the upper and lower tracks calculated by the standard deviation, the formation of three mesh band, which are very practical in the price difference arbitrage transaction.&lt;br /&gt;&lt;br /&gt;After testing, operating according to this strategy, the overall income is relatively stable, although the income is not very much each time without considering the handling fee and impact cost. It should be noted that due to the statistical arbitrage, there is a risk of reverse expansion of the price difference. We must consider the stop-loss problem when designing. Secondly, we also need to pay attention to the impact cost. When the liquidity of the two contracts involved in the transaction shrinks, it will have a great impact on the income, and investors should avoid it as appropriate.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;4. Advanced iteration of CTA strategy development&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;4.1 Avoid the pitfalls of futures CTA strategy&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In the last two classes, we wrote a trend strategy in MyLanguage and an arbitrage strategy in JavaScript. We didn&amp;#39;t see any problems in the strategy backtest. However, quantitative trading is not a program, whose backtest can be done directly without any problems.&lt;br /&gt;&lt;br /&gt;In fact, the backtest is only a simulation of the strategy. It is only used to evaluate the performance of the strategy in the historical data. It allows traders to evaluate and discard some trading strategies quickly.&lt;br /&gt;&lt;br /&gt;In many cases, strategies that look great in the backtest often fail to meet the backtest standard in the real market for a variety of reasons. Some of them are beyond the control of traders, but some of the failures are caused by common or potential errors.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Static data and dynamic data&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;We should have a concept of static data and dynamic data to quantify first. In the backtest, we use static historical data. The price of opening high and closing low with each K-line is complete, and each transaction signal can be closed 100%. But the data in the real market is dynamic. For example, if the maximum price is greater than the maximum price within 1 hour of opening, buy. But if the current K-line has not finished, the maximum price is dynamic, and the trading signal may flicker back and forth. This situation indicates that the strategy uses the future function in judging the conditions of the buy and sell trading.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Future function&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;What is the future function? Let&amp;#39;s take a look at Baidu Encyclopedia&amp;#39;s explanation first: A quantity depends on another quantity, such as quantity A and quantity B. If B changes, A changes, then A is a function of B. If B is a later quantity, A is an earlier quantity, A changes with B, and A is a future function of B. You may be confused.&lt;br /&gt;&lt;br /&gt;Generally speaking, it is a function of quoting future data, such as forecasting tomorrow&amp;#39;s price with tomorrow&amp;#39;s price. If a technical indicator contains a future function, its signal is uncertain. It is often the current transaction signal. When the next K-line appears, the signal disappears or changes position.&lt;br /&gt;&lt;br /&gt;The closing price is a future function. The closing price is always changing until the latest K-line runs out. You must wait until the K-line runs out to determine the closing price. Since the closing price itself is a future function, all technical indicators based on the closing price are also future functions.&lt;br /&gt;&lt;br /&gt;Therefore, if a technical indicator uses the confirmed closing price as the basic data, the trading signal will not change no matter how long it has passed, it can be said that the technical indicator does not refer to the future function. But the basic data it uses is the unconfirmed closing price, so this technical indicator refers to the future function, and the trading signal may change in practical application.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Past prices&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;The future function uses the future price, which may also use the past price on the contrary. This is also a problem that many novices tend to ignore. To better illustrate this problem in the future, let&amp;#39;s take an example: if the current maximum price is greater than the maximum price within 1 hour after the opening, buy at the opening price. Obviously, there is no problem with the conditions of the buying and selling signal, but the price of the order has used the past price.&lt;br /&gt;&lt;br /&gt;In the backtest, the strategy is normal, because the backtest engine based on static data can be closed 100% only if there is a buy signal. However, when the highest price is greater than the highest price within 1 hour after the opening, it is certain that the order cannot be issued at the previous price opening price.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Price vacuum&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;The so-called price vacuum refers to the prices displayed on the K-line chart, but the prices that cannot be traded in the real market, mainly divided into the following cases:&lt;br /&gt;&lt;br /&gt;- 1. Anyone who has done trading knows that it is difficult to buy when the price is up and difficult to sell when the price is down. But it can be concluded in the backtest.&lt;br /&gt;- 2. The matching mechanism of the exchange is price priority and time priority. Some varieties will often have a large number of orders in the market. If you are trading with orders in the real market, you must rank behind others&amp;#39; orders. You can only trade after others&amp;#39; orders are traded. Even before the price can be traded, the price has changed. However, in the backtest, if your strategy is to deal with the order, you will deal in time, which is different from the real market environment.&lt;br /&gt;- 3. If you use an arbitrage strategy, the profit of the backtest is very high, because it is assumed that you have captured these price differences every time. In reality, many price differentials can&amp;#39;t be grabbed, or only one leg can be grabbed. Generally speaking, it must be the one that is not conducive to your direction. Then you need to fill the other leg immediately. At this time, the sliding point is no longer 1 or 2 points, and the arbitrage strategy itself aims to earn the price difference of these points. This situation cannot be simulated in the backtest. The real profit is not as good as the backtest.&lt;br /&gt;- 4. Although the black swan event is not used commonly, it still has a great impact on quantitative trading. As shown in the chart below, in the case of the black swan event of the foreign exchange Swiss franc, both high and low prices can be seen from the chart. In fact, in the extreme market of the day, the middle price is vacuum, and a large number of stop loss orders cause stampede events. The liquidity is zero, and it is very difficult to deal with, but it can stop loss in the backtest.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150381
" title="https://stocksharp.com/file/150381
"&gt;https://stocksharp.com/file/150381
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Overfitting&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Overfitting is a common mistake made by quantitative trading beginners. What is overfitting? To take a simple example, some people use a great deal of exercises to memorize each question in the school exam. He can&amp;#39;t do it if the subject changes a little during the exam. Because he memorized the practice of each question in a very complex way, he did not abstract the general rules.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150380
" title="https://stocksharp.com/file/150380
"&gt;https://stocksharp.com/file/150380
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Like the chart above, a model can adapt to data perfectly as long as it is complex enough. This is also true of overfitting in quantitative trading. If your strategy is complex and it has many external parameters, there will always be one or several parameters that can perfectly fit the historical market in the limited historical data backtest.&lt;br /&gt;&lt;br /&gt;However, in the future real market, the price change may exceed your strategy limit. In fact, the essence of quantitative trading strategy development is the process of matching local non-random data from a large number of seemingly random data. Therefore, we need to use statistical knowledge to avoid the trap. How do we do it?&lt;br /&gt;&lt;br /&gt;The compromise solution is to use intra-sample and extra-sample data. Divide the whole data into two parts, and use the intra-sample as the training set, which is responsible for the data backtest. The extra-sample is used as the test set and is responsible for verification. If there is little historical data, you can also use the cross-test method.&lt;br /&gt;&lt;br /&gt;If you find that the data out of the sample performs not well, and you feel that it is too bad to lose the model or you are unwilling to admit that your model is not good, and you continue to optimize the model for the extra-sample data until the extra-sample data also perform well, then you must lose your money in the end.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Survivorship bias&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;The survivorship bias can be explained by the following examples:&lt;br /&gt;1. When standing at the tuyere, pigs will fly.&lt;br /&gt;2. People who sell parachutes online are praised, because people with problems with parachutes don&amp;#39;t live anymore.&lt;br /&gt;3. The reporter interviewed whether passengers have bought tickets on the bus, because people without tickets can&amp;#39;t get on the bus at all.&lt;br /&gt;4. The media advertises that the lottery can be won, because the media will not actively promote people who do not win the lottery.&lt;br /&gt;&lt;br /&gt;In the above example, we can find that the information that people usually receive is actually filtered, which makes a large number of data or samples ignored selectively, and the result is that the conclusions based on survivorship bias have deviated from real-time. So in quantitative trading, we also need to focus on whether the results of the backtest are part of luck. In many cases, the results of the backtest may be the best performance in the whole backtest. Pay attention to the following figure:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150382
" title="https://stocksharp.com/file/150382
"&gt;https://stocksharp.com/file/150382
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- Left chart (semblance): A very good trading strategy. Without major withdrawal, investors can obtain stable investment returns.&lt;br /&gt;- Right chart (the reality): This is only the best one in 200 random trading backtests.&lt;br /&gt;&lt;br /&gt;The picture on the left is a very good trading strategy. The capital curve is good, and there is no significant withdrawal, and stable profit returns can be obtained. But look at the picture on the right. It is only the best one in the hundreds of backtest transactions. On the other hand, when we look at the financial market, there are always more stars and less longevity stars. If the strategy of the traders is consistent with the market situation, then the market every year can create a batch of stars, but it is difficult to see longevity stars who can make steady profits for more than three years in a row.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Cost shock&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Unless you are pending an order, you may have a sliding price when trading. On the varieties with active trading, the bid-price and ask-price are usually different in one point. On the varieties with inactive trading, the difference may be greater. Every time you want to take the initiative to close a deal, you need one point difference at least, or even more. However, in the backtest, we do not need to consider the issue of transaction, as long as there is a signal, we can trade, so in order to simulate the real trading environment, we must add one sliding price at least.&lt;br /&gt;&lt;br /&gt;Especially for the strategy that is traded more frequently, if the sliding price is not added when the strategy is backtested, the capital curve will always tilt upward, and once the reasonable sliding price is added, it will turn to a loss immediately. In addition, this phenomenon is not only caused by point difference, but also needs to be considered in the real trading environment: network delay, software and hardware systems, server response and other issues.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Strategy capacity&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;The same strategy will be quite different in efficient and inefficient markets, even the opposite. For example, in inefficient markets such as domestic stock markets, commodity futures, and foreign digital currencies, due to the small base of trading volume, the capacity of high-frequency strategy itself is not very large, and there is no profit space for more people, and even the strategy that was originally profitable has become a loss. But in an efficient foreign exchange market, it can accommodate many different types of high-frequency strategies.&lt;br /&gt;&lt;br /&gt;The above are the problems and pitfalls that may occur in the development and use of strategies. For an experienced trading system developer, backtesting is a must. Because it can tell you whether a strategic idea can be verified in historical transactions. But many times, backtesting does not mean that it will be profitable in the future. Because there are too many pitfalls in the backtest, you won&amp;#39;t understand without paying for some lessons. This course can help you avoid many quantitative detours and pitfalls at least.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4.2 Establish the best position management&lt;/b&gt;&lt;br /&gt;In &amp;quot;Reminiscences of a stock operator&amp;quot;, there is a very interesting paragraph: the Old Turkey (formerly known as Partridge) who is in the same securities company as the hero Livermore, always makes a big deal. When he was advised to sell after taking profits and buy again after the stock price had retraced. The Old Turkey always intoned: No, you know, this is a bull market!&lt;br /&gt;&lt;br /&gt;Even Livermore sighed finally: There is nothing remarkable about the trend. There are always many people who are bullish in the bull market and bearish in the bear market. But they are always good at bargaining with the market, trying to buy at the lowest point and sell at the highest point. Like the Old Turkey, it is those who see the market and hold their positions that really make a great fortune, which is also the most difficult to learn. This not only faces the choice of target and timing, but also faces a more important question: how much position (risk) should we hold (bear)?&lt;br /&gt;&lt;br /&gt;All failed traders have one-sided thinking. When trading, greedy people only see profits rather than risks, while timid people only see risks rather than profits. Greedy and timid people forget risks when rising, and forget profits when falling. However, successful traders will consider both risks and returns, that is to say, they will bear several dollars of risk for every dollar they earn. Then the index to measure return and risk is the return risk ratio.&lt;br /&gt;&lt;br /&gt;Many people know that the risk is as big as the profit, that is, the return is proportional to the risk. In the view of some people, the relationship between return and risk should be as follows: the horizontal axis is the percentage of risk, and the vertical axis is the percentage of return:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150387
" title="https://stocksharp.com/file/150387
"&gt;https://stocksharp.com/file/150387
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;But in the actual transaction, the return and risk are far from being as simple as two points of a line, at least it doesn&amp;#39;t always move linearly. The real risk is the maximum amount of loss that can be taken with the expected return, or what we call the maximum volatility. Although sometimes the maximum floating loss does not always equal the closing loss in terms of the outcome of the trade, the maximum floating loss is real.&lt;br /&gt;&lt;br /&gt;From this, we can know that the ratio of return to risk in the figure above is not the real performance. In a real trading environment, the ratio of return to risk should be the same as in the chart below:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150388
" title="https://stocksharp.com/file/150388
"&gt;https://stocksharp.com/file/150388
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s look at the chart above. The yellow curve shows the fluctuation of net worth at different risks. With the expected returns expanding, the risks are also expanding gradually. If we set bankruptcy at 0.5, that is, the maximum loss reaches 50%, then this is a failed trading strategy. Although the final return of the strategy is positive from the result, it has already gone bankrupt in the middle.&lt;br /&gt;&lt;br /&gt;Even if your strategy is a positive one, it will be liquidations under the wrong position management. So from this point of view, how much to buy and sell is more important than when to buy and sell. How to manage the position scientifically has become a fundamental issue in financial transactions. So before trying to solve this problem, let&amp;#39;s see how to bet scientifically in gambling.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150386
" title="https://stocksharp.com/file/150386
"&gt;https://stocksharp.com/file/150386
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s take the coin toss as an example. Suppose that both sides of a coin are equally weighted. If there is a head profit of 2 yuan and a tail loss of 1 yuan, it is obvious that this is a positive expectation game. The winning rate is 50% and a loss of 2. Here comes the question: Now that you have 100 yuan, how can you repeat the bet so that 100 yuan can reach 1 million yuan at the fastest speed.&lt;br /&gt;&lt;br /&gt;If we don&amp;#39;t think carefully, we will think that since the return of each bet is 50% * 2-50% * 1, that is, 50%, then in order to achieve the maximum return quickly, we should invest as much capital as possible in each bet. This bet must be 100%.&lt;br /&gt;&lt;br /&gt;However, it is obvious that it is unreasonable to invest 100% of the principal in every game of gambling, because as long as you lose the principal once, it will be lost, even if it is very unlikely. Because as long as you gamble enough times, losing money will happen definitely.&lt;br /&gt;&lt;br /&gt;Someone may ask, since 100% bet is unreasonable, what about 90% or lower bet? In fact, to solve this problem, we can make an experiment to simulate the gambling game and see how the result of each bet is. As shown in the following chart:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150384
" title="https://stocksharp.com/file/150384
"&gt;https://stocksharp.com/file/150384
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From the chart, we can see that when we gradually reduce the position from 90%, 80%, 70%, 60% and 50%, in the same gamble, the results are completely different. Careful friends may have noticed that with the gradual reduction of the position, the final capital is expanding gradually.&lt;br /&gt;&lt;br /&gt;Then some people may ask whether the smaller the bet each time is, the better, such as 10%. It is impossible to calculate every bet proportion. This is the problem to be solved by the famous Kelly Criterion. In statistics, Kelly Criterion can maximize the long-term growth rate of a strategy with positive expectation of repeated bets, and it can calculate the best bet ratio in each bet.&lt;br /&gt;&lt;br /&gt;Not only that, assuming that the principal and the bet can be divided endlessly, it is impossible to go bankrupt in any bet by using the Kelly Criterion. Especially in the practical application of financial transactions, it is a position management strategy with both attack and defense. Let&amp;#39;s look at how Kelly Criterion is calculated, and see the following figure:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150383
" title="https://stocksharp.com/file/150383
"&gt;https://stocksharp.com/file/150383
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- f is the optimal betting ratio for the available capital;&lt;br /&gt;- b is the odds ratio, which can also be called the profit/loss ratio in trading;&lt;br /&gt;- p is the success rate;&lt;br /&gt;- q is the failure rate.&lt;br /&gt;&lt;br /&gt;Then we can calculate the gambling example in this lesson according to the Kelly Criterion. The initial capital of 100 yuan can reach 1 million yuan at the fastest speed by using the betting ratio when the winning ratio is 50% and the odds is 2. Set into the Kelly Criterion, the calculation process is as follows:&lt;br /&gt;&lt;br /&gt;(0.5*(2+1) -1)/2=0.25&lt;br /&gt;&lt;br /&gt;The winning rate of 50% is 0.5. Multiply the odds by 2 plus 1, then subtract 1, and then divide by 2. The calculation result is 0.25. That is to say, in each bet, using 25% of the principal, you can reach 1 million yuan at the fastest speed. We can simulate manually according to the calculation results to see if it is correct.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150385
" title="https://stocksharp.com/file/150385
"&gt;https://stocksharp.com/file/150385
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The figure above is the result of manual simulation. Please see the last line. In the same bet, after more than 100 rounds, 25% of the positions reached 1 million yuan first. The result of 90%, 80%, 70% and 60% positions is negative, which shows that even a positive expectation trading strategy will go bankrupt under the wrong position management.&lt;br /&gt;&lt;br /&gt;We can also see that 50% of the positions will not lose or win in the end, which is also consistent with the result of the law of large numbers. In order to further illustrate the problem, a position of 10% was also added in the manual simulation. Although the final result was a positive return, the effect was several orders of magnitude worse than that of a position of 25%.&lt;br /&gt;&lt;br /&gt;You can see the power of Kelly Criterion. If you choose 10% of the principal position in the actual application, your principal will become more than 30,000 in more than 100 bets. Although the return is large, compared with 25% of the principal position, it is equivalent to no profit. This is the power of knowledge.&lt;br /&gt;&lt;br /&gt;If you want to make profits from Kelly Criterion in life, you need to meet the application conditions of Kelly Criterion. There is no doubt that this bet must come from the financial market. Especially in quantitative trading, we can roughly calculate the corresponding winning ratio and odds through historical data backtesting.&lt;br /&gt;&lt;br /&gt;Of course, the practical application of Kelly Criterion in financial transactions cannot be so simple, and there are many details to be dealt with, such as the cost of capital in leveraged transactions, the capital and position in real transactions can not be divided wirelessly, and the winning ratio and loss ratio in transactions are changing dynamically, and so on. Whatever, Kelly Criterion shows us how to establish the best position management method.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y6yaRDtrGn92RTJJ6GDDaOrcYRqX-_tIfOKBwLwx535erfDmGmRz7j8nf3ZQMsXwCMxDKU0hNcvmT0f_iFgln5iJYfGH-v9R3t_0CjD3DbHONKu4c0dfLcPYrt74ZdeAkYF3Z91GLU5KgL42FxWwWflQ" title="https://blog.mathquant.com/2023/02/07/from-quantitative-trading-to-asset-management-cta-strategy-development-for-absolute-return.html"&gt;https://blog.mathquant.c...for-absolute-return.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25703/</id>
    <title type="text">9 trading rules help a trader earn $46,000 from $1,000 in less than a year</title>
    <published>2024-04-18T02:45:58Z</published>
    <updated>2024-04-18T02:45:58Z</updated>
    <author>
      <name>Quant</name>
      <uri>https://stocksharp.com/users/186455/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#strategy" />
    <category term="#market" />
    <category term="#bitcoin" />
    <category term="#return" />
    <category term="#profit" />
    <category term="#loss" />
    <category term="#FMZQuant" />
    <category term="#invest" />
    <content type="html">No, I am not a successful trader. I have been lucky many times, and I am still refining and trying strategies; On the other hand, I am still one of the people who constantly trade to increase the profit of the portfolio. Although some results can be attributed to luck, most of them are based on fundamentals, good habits and experience.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;The result of good habits&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Miles is the co-founder of Pure Investments. In May 2017, he began with $1,000, which he saved by saving 10% of his salary every month. Today, his income is $46,000; In other words, he increased his portfolio by 46 times in less than one year.&lt;br /&gt;&lt;br /&gt;Similarly, after starting Pure Investments in September 2017, Miles accepted his first community member, who was nicknamed &amp;quot;SP&amp;quot; on the Discord channel. When SP started trading, it invested $40,000. By January 2018, his investment income had exceeded $1 million.&lt;br /&gt;&lt;br /&gt;Although the cryptocurrency market price is extremely volatile, and all investors are affected by price fluctuations, including Miles, SP, me and you, good habits will help reduce losses and maximize profits.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;9 cryptocurrency trading rules&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Please note that these are not specific investment suggestions. Please bear your own investment risk!&lt;br /&gt;&lt;br /&gt;1. Only invest in what you can lose. During the price collapse in January 2018, many amateur investors were cleaned out of the market. Their funny performance is that the ground is full of broken monitors, the balance in laptops and bank accounts has shrunk significantly. Although sequential trading steps and methods are important, there is no doubt that the principles behind these trading steps and methods are more important. Once your funds are converted into cryptocurrency, by default that the money has been lost. The market can never guarantee that you can take it back. The loss is not only from the decline of the market; External factors such as hackers, loopholes and government regulation may mean that you will never see any part of the funds again. If you can&amp;#39;t afford to lose when investing, you need to step back and reassess your current financial situation, because what you will do will be accompanied by despair. This includes: using credit cards, mortgages, applying for loans, selling everything and traveling around the world (which sounds fascinating).&lt;br /&gt;&lt;br /&gt;2. Always pay attention to Bitcoin. Most Altcoins (every cryptocurrency except Bitcoin) are more closely related to Bitcoin than Asian currencies and the US dollar during the Asian financial crisis. If the price of Bitcoin rises sharply, people will try to exit the Altcoins to gain BTC profits, and the price of Altcoins will decrease; On the contrary, if the price of Bitcoin decreases sharply, the price of Altcoins will also decrease, because people withdraw from Altcoins to exchange for fiat currency. When Bitcoin shows a sideways shock or fall, the best period for the growth of Altcoins will appear.&lt;br /&gt;&lt;br /&gt;3. Do not put all the eggs in one basket. Investment needs diversification. Although the amount you invest in digital currency increases the potential to earn more profits, the possibility of losing more will also be magnified. Another way of thinking is to take the cryptocurrency market as a whole; If you think this is just the beginning, the entire market value of cryptocurrency will increase. What is the probability that the market value increase will be driven by one currency rather than many currencies? The best way to safely capture the overall growth of cryptocurrencies is to diversify and benefit from multiple currencies. In addition, the interesting fact is that from January 2016 to January 2018, Corgicoin increased by 60,000 times and Verge increased by 13,000 times. Over the same period, Bitcoin has increased 34 times. Although you will get impressive benefits from Bitcoin, expanding to other currencies may give you greater benefits.&lt;br /&gt;&lt;br /&gt;4. Don&amp;#39;t be greedy. It is human nature to have losses and gains. When a currency begins to grow, our inner greed follows. If a currency increases by 30%, why not consider profits? Even if the target is set at 40% or 50%, if a currency fails to meet the target, you should get some profits from it at least. If you wait too long or try to exit at a higher point, you may lose the profits you have earned, or even turn profits into losses. If you want to continue to gain potential profits, form the habit of stopping profits and looking for re-entering the market.&lt;br /&gt;&lt;br /&gt;5. Don&amp;#39;t invest blindly. Some people in the world will sell a pair of glasses to a blind person without limit, as long as the business can bring him profits. Such people also exist in the cryptocurrency market, and they will take every opportunity to deceive investors with little knowledge. They will tell you what to buy or claim that some currencies will decrease, just to raise or depress the price so that they can cash out. Due to the highly speculative nature of today&amp;#39;s cryptocurrency market, an excellent investor must always conduct his own research in order to take full responsibility or potential investment results. Even if the information comes from the best investors, it is only a good information at best, but it is by no means a commitment, so you can still incur losses.&lt;br /&gt;&lt;br /&gt;6. Don&amp;#39;t worry about profits and losses. This is where people often lose money. A typical case of manipulation in December, the joint speculation of the two media, the announcement of the Chicago Mercantile Exchange and the Chicago Options Exchange, and a large number of news pushed the price of Bitcoin from $10,000 to $20,000. Since then, Bitcoin has fallen to a low of $9,000, and is currently about $11,000. It&amp;#39;s easy to go back and say, &amp;quot;If I only waited for one month, I could buy it at the price of $9,000 instead of waiting for Bitcoin to reach $20,000 again, so that I could make both ends meet.&amp;quot; But the reality is that the decision of insatiable greed and blind investment will indeed make Bitcoin reach a record high, but it is also a terrible decision to stand firmly at a high position. In any speculative market, if an investment target blowouts rapidly, it will certainly correct itself - it is only a matter of time. The correction mechanism after excessive speculation almost always follows. Although trying to jump on a train at full speed sounds as exciting as a James Bond movie, I believe most of us agree that if we wait for it at the next station, we may retain some limbs.&lt;br /&gt;&lt;br /&gt;7. Classify your investment and try to look at the long line chart. During your research, you will eventually find that you have encountered several different types of currencies. For some of them, you believe they have excellent teams, good vision, amazing publicity and successful implementation records. That&amp;#39;s great! Put them into the medium or long-term vision, and then marinate them into delicious bacon. When the price falls, do not consider selling, because anything in the medium-term or long-term portfolio should remain unaffected by the price for a period of time. BNB is a good example of currency that Miles considers a long-term holding. Recently, it has declined by 20% temporarily. In our community, we have witnessed some panic selling to protect profits. A week later, it rose nearly three times in a period of time.&lt;br /&gt;&lt;br /&gt;8. Always learn from mistakes. Never wait for a position to close when you are close to liquidation. Always evaluate the market situation and try to find out why it happened. Take this assessment as the basis for your next action, and if you continue to do so, you will know more than before and make more informed decisions. We are all amateurs, and we will lose money in the whole trading process. In his first month of trading, Miles lost from $1,000 to $300. Most of these losses were caused by selling through fear. No one is perfect, no one will win every transaction. Don&amp;#39;t let losses discourage you, because the reality is that if you choose to learn from losses, they will make you a better trader.&lt;br /&gt;&lt;br /&gt;9. If you are conducting any trading activities, please set a stop loss. For any currency that is not in your medium or long-term holding, always set a stop loss. This is important for several reasons - the most obvious is to reduce your losses. But more importantly, you force yourself to decide the acceptable loss point, and because you now have a reference point, you can measure the effectiveness of your reservation or adjustment of future transactions. Sometimes, during the decline of the market, Altcoins may plummet and can be used to re-enter at a lower price through automatic selling.&lt;br /&gt;&lt;br /&gt;10. One extra note: always check the currency code. Code symbols are not universal and may vary from exchange to exchange in rare cases. However, these small probability situations may still turn around and bite you. For example, Bitcoin cash is traded as BCH in some exchanges and BCC in other exchanges. BCC, also the code of BitConnect, recently went bankrupt as a Ponzi scheme. If you think you are buying Bitcoin cash and end up buying BitConnect, you will lose a lot of money.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;You don&amp;#39;t have to do it alone&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Although these rules are by no means the only courses you need, they are definitely a good starting point. But sometimes things are easier said than done. For example, you still have the iron will to resist the sell button when you watch the value of your portfolio plummet. One of the best solutions I have found is to join a like-minded cryptocurrency investor community. Educated digital currency traders and community members will fully support your work and will be with you during the tough times.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y6-cLTQvjwVD6lNcTnaqoPVf309XHYWVEWyTJCI22hX1eu2pw2zEm-omCzITAuEBAYjxjS5YbF-VMZm84u3r4mFPfbPOTyWyv9apGa5vBM9xtbq0xoB9DHdKsUEMx0qHorw" title="https://blog.mathquant.com/2023/02/07/9-trading-rules-help-a-trader-earn-46000-from-1000-in-less-than-a-year.html"&gt;https://blog.mathquant.c...in-less-than-a-year.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25702/</id>
    <title type="text">When FMZ encounters ChatGPT, an attempt to use AI to assist in learning quantitative trading</title>
    <published>2024-04-18T02:05:46Z</published>
    <updated>2024-04-18T02:05:46Z</updated>
    <author>
      <name>Quant</name>
      <uri>https://stocksharp.com/users/186455/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#strategy" />
    <category term="#code" />
    <category term="#risk" />
    <category term="#FMZQuant" />
    <category term="#ChatGPT" />
    <category term="#Pine" />
    <category term="#AI" />
    <category term="#backtest" />
    <content type="html">&lt;span style="font-size:140%"&gt;&lt;b&gt;ChatGPT&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;ChatGPT has been very popular recently. There are various videos applied to real-world scenarios on the Internet. Let me introduce what ChatGPT is briefly. ChatGPT is a language model developed by OpenAI. Unlike previous AI, ChatGPT has very strong language understanding ability. There are many videos about the introduction, registration and use of ChatGPT on the network. I will not repeat them here.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;When FMZ encounters ChatGPT&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;In the field of quantitative trading learning, beginners have always been very difficult at the entry stage. Because most beginners are based on 0, they lack both grammatical knowledge and thinking logic for code, so they will feel it is very difficult to learn.&lt;br /&gt;&lt;br /&gt;OK, the next article is not written by me. Let&amp;#39;s show some appetizers.&lt;br /&gt;&lt;br /&gt;**part1**&lt;br /&gt;When FMZ encounters ChatGPT, an attempt to use AI to assist in learning quantitative trading&lt;br /&gt;&lt;br /&gt;As a beginner, I have been looking for effective ways to learn quantitative trading. After searching online, I found FMZ and ChatGPT. So I decided to try to use them to deepen my understanding of quantitative trading.&lt;br /&gt;&lt;br /&gt;First, I learned how to use PINE script to write a trading strategy on FMZ. On this platform, I found templates for various strategies and tested their effects by adjusting parameters. In addition, I also learned how to use the backtesting function to evaluate the returns of the strategy.&lt;br /&gt;&lt;br /&gt;Next, I use ChatGPT to get more help. On this platform, I found an AI assistant named Assistant, who can answer my various questions. Through communicating with Assistant, I learned a lot of useful knowledge and got many valuable suggestions.&lt;br /&gt;&lt;br /&gt;In the process of using FMZ and ChatGPT, I gained a lot. Not only learned how to write trading strategies, but also gained more knowledge about quantitative trading. I believe that as I continue to learn and practice,&lt;br /&gt;&lt;br /&gt;**part2**&lt;br /&gt;I will be able to further improve my trading skills and achieve better returns in the future.&lt;br /&gt;&lt;br /&gt;Although using FMZ and ChatGPT can get a lot of help, I also realize that quantitative trading is a continuous learning process. I still have a lot to learn, and I will continue to work hard to improve myself.&lt;br /&gt;&lt;br /&gt;In the end, I hope my attempt can help other beginners. If you also want to learn quantitative trading, try FMZ and ChatGPT platforms, which may become powerful assistants for you to learn.&lt;br /&gt;&lt;br /&gt;**part3**&lt;br /&gt;Of course, quantitative trading is not an easy task. It requires continuous learning and practice to improve skills. Therefore, I also suggest that you participate in various training courses and community activities, exchange trading experience with professionals, and always staycurious and inquisitive.&lt;br /&gt;&lt;br /&gt;In addition, it is also very important to pay attention to risk management. There are many uncertain factors in quantitative trading, so we must set a reasonable stop-loss strategy and select the trading variety and trading period carefully.&lt;br /&gt;&lt;br /&gt;**part4**&lt;br /&gt;To sum up, I believe using FMZ and ChatGPT platforms to learn quantitative trading is a good choice. They provide us with rich learning resources and assistance, so that we can grasp knowledge and practice easily. However, we should also remember that learning quantitative trading is a continuous process, and we need to make continuous efforts to achieve greater success in this field.&lt;br /&gt;&lt;br /&gt;Ok, I&amp;#39;ll start writing again, you can believe it! The above part1 ~ part4 are written by ChatGPT. Let me show some evidence:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150367
" title="https://stocksharp.com/file/150367
"&gt;https://stocksharp.com/file/150367
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When FMZ encounters ChatGPT, an attempt to use AI to assist in learning quantitative trading&lt;br /&gt;&lt;br /&gt;As a beginner, I have been looking for effective ways to learn quantitative trading. After searching online, I found FMZ and ChatGPT. So I decided to try to use them to deepen my understanding of quantitative trading.&lt;br /&gt;&lt;br /&gt;First, I learned how to use PINE script to write a trading strategy on FMZ. On this platform, I found templates for various strategies and tested their effects by adjusting parameters. In addition, I also learned how to use the backtesting function to evaluate the returns of the strategy.&lt;br /&gt;&lt;br /&gt;Next, I use ChatGPT to get more help. On this platform, I found an AI assistant named Assistant, who can answer my various questions. Through communicating with Assistant, I learned a lot of useful knowledge and got many valuable suggestions.&lt;br /&gt;&lt;br /&gt;In the process of using FMZ and ChatGPT, I gained a lot. Not only learned how to write trading strategies, but also gained more knowledge about quantitative trading. I believe that as I continue to learn and practice,&lt;br /&gt;&lt;br /&gt;Go on:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150367
" title="https://stocksharp.com/file/150367
"&gt;https://stocksharp.com/file/150367
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I will be able to further improve my trading skills and achieve better returns in the future.&lt;br /&gt;&lt;br /&gt;Although using FMZ and ChatGPT can get a lot of help, I also realize that quantitative trading is a continuous learning process. I still have a lot to learn, and I will continue to work hard to improve myself.&lt;br /&gt;&lt;br /&gt;In the end, I hope my attempt can help other beginners. If you also want to learn quantitative trading, try FMZ and ChatGPT platforms, which may become powerful assistants for you to learn.&lt;br /&gt;&lt;br /&gt;Go on:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150367
" title="https://stocksharp.com/file/150367
"&gt;https://stocksharp.com/file/150367
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Of course, quantitative trading is not an easy task. It requires continuous learning and practice to improve skills. Therefore, I also suggest that you participate in various training courses and community activities, exchange trading experience with professionals, and always stay curious and inquisitive.&lt;br /&gt;&lt;br /&gt;In addition, it is also very important to pay attention to risk management. There are many uncertain factors in quantitative trading, so we must set a reasonable stop-loss strategy and select the trading variety and trading period carefully.&lt;br /&gt;&lt;br /&gt;To sum up, I believe using FMZ and ChatGPT platforms to learn quantitative trading is a good choice.&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s start the topic again.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;Let AI write a strategy for me&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;If I am an introductory learner of the PINE language on the FMZ platform with 0 basics, I can put forward a simple requirement for ChatGPT to see if AI can help me write code:&lt;br /&gt;&lt;br /&gt;Propose requirements:&lt;br /&gt;&lt;br /&gt;Can you use the PINE script to write a double EMA strategy for me? The moving average index of different periods is that the up cross is to open long positions, the down cross is to open short positions, and the stop loss is 100 points. And give me the complete PINE script strategy. Use version control code://@ version=4&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150367
" title="https://stocksharp.com/file/150367
"&gt;https://stocksharp.com/file/150367
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Certainly. This is an example of using PINE script to write a double EMA strategy, starting with version control code://@ version=4&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150368
" title="https://stocksharp.com/file/150368
"&gt;https://stocksharp.com/file/150368
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In this code, we first set two parameters that can be adjusted: long-term average period and short-term average period. Then, we calculate the two moving averages and use the statement to determine whether there is an up cross or a down cross. If an up cross occurs, go long; if a down cross occurs, go short. Finally, we set a stop loss point. If the price falls below the stop loss point, the position will be closed.&lt;br /&gt;&lt;br /&gt;Note: This is only an example, and it does not guarantee that the strategy will yield good returns. Risk should be carefully considered when using any trading strategy.&lt;br /&gt;&lt;br /&gt;```&lt;br /&gt;// @version=4&lt;br /&gt;strategy(&amp;quot;double EMA strategy&amp;quot;, overlay=true)&lt;br /&gt;&lt;br /&gt;longTerm = input(title=&amp;quot;long-term average period&amp;quot;, type=input.integer, defval=200)&lt;br /&gt;shortTerm = input(title=&amp;quot;short-term average period&amp;quot;, type=input.integer, defval=50)&lt;br /&gt;stopLoss = input(title=&amp;quot;stop loss point&amp;quot;, type=input.integer, defval=100)&lt;br /&gt;&lt;br /&gt;longMA = sma(close, longTerm)&lt;br /&gt;shortMA = sma(close, shortTerm)&lt;br /&gt;&lt;br /&gt;if (shortMA &amp;gt; longMA)&lt;br /&gt;    strategy.entry(&amp;quot;go long&amp;quot;, strategy.long)&lt;br /&gt;if (shortMA &amp;lt; longMA)&lt;br /&gt;    strategy.entry(&amp;quot;go short&amp;quot;, strategy.short)&lt;br /&gt;&lt;br /&gt;strategy.exit(&amp;quot;stop loss&amp;quot;, &amp;quot;go long&amp;quot;, stop=strategy.position_avg_price - stopLoss)&lt;br /&gt;strategy.exit(&amp;quot;stop loss&amp;quot;, &amp;quot;go short&amp;quot;, stop=strategy.position_avg_price + stopLoss)&lt;br /&gt;```&lt;br /&gt;It wrote the code out. Let me run it on the FMZ platform backtest system!&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150369
" title="https://stocksharp.com/file/150369
"&gt;https://stocksharp.com/file/150369
&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150370
" title="https://stocksharp.com/file/150370
"&gt;https://stocksharp.com/file/150370
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;PINE script is running!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;Next, let ChatGPT help us explain the strategy, which can also help us learn about quantitative trading.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ask the question:&lt;br /&gt;```&lt;br /&gt;strategy(&amp;quot;test&amp;quot;, overlay = true)&lt;br /&gt;&lt;br /&gt;varip a = na&lt;br /&gt;varip highPrice = na&lt;br /&gt;varip isTrade = false &lt;br /&gt;varip offset = 30&lt;br /&gt;&lt;br /&gt;if not barstate.ishistory and not isTrade&lt;br /&gt;    strategy.entry(&amp;quot;test 1&amp;quot;, strategy.long, 1)&lt;br /&gt;    strategy.exit(&amp;quot;exit 1&amp;quot;, &amp;quot;test 1&amp;quot;, 1, trail_price=close+offset, trail_offset=offset)&lt;br /&gt;    a := close + offset&lt;br /&gt;    runtime.log(&amp;quot;The price per point is:&amp;quot;, syminfo.mintick, &amp;quot;, current close:&amp;quot;, close)&lt;br /&gt;    isTrade := true &lt;br /&gt;&lt;br /&gt;if close &amp;gt; a and not barstate.ishistory&lt;br /&gt;    highPrice := na(highPrice) ? close : highPrice&lt;br /&gt;    highPrice := close &amp;gt; highPrice ? close : highPrice&lt;br /&gt;&lt;br /&gt;plot(a, &amp;quot;trail_price trigger line&amp;quot;)    &lt;br /&gt;plot(strategy.position_size&amp;gt;0 ? highPrice : na, &amp;quot;current highest price&amp;quot;)&lt;br /&gt;plot(strategy.position_size&amp;gt;0 ? highPrice-syminfo.mintick*offset : na, &amp;quot;moving stop loss trigger line&amp;quot;)&lt;br /&gt;&lt;br /&gt;Can you explain the detailed logic of this script?&lt;br /&gt;```&lt;br /&gt;Screenshots:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150372
" title="https://stocksharp.com/file/150372
"&gt;https://stocksharp.com/file/150372
&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150367
" title="https://stocksharp.com/file/150367
"&gt;https://stocksharp.com/file/150367
&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150371
" title="https://stocksharp.com/file/150371
"&gt;https://stocksharp.com/file/150371
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It can get the meaning of this script and summarize it. I am wondering if there is a quantitative trading researcher answering my question behind this page...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;Imperfections&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Of course, ChatGPT is not perfect yet. For example, when communicating with it in Chinese, it often breaks off. It needs to continue with the dialogue of &amp;quot;continue to speak&amp;quot;. For some questions that it doesn&amp;#39;t know very well, it will talk nonsense with you. We need to combine search engines to determine the answers given, and we can&amp;#39;t blindly believe it. However, ChatGPT is still very helpful for quantitative trading learning on FMZ. It can help us understand the code that is difficult to understand. At least it can give us some hints and inspiration, so that we know what to learn. It can also help us write some simple code prototypes, give some basic solutions and code implementation. There should be more advanced methods. We can continue to explore in the future. We hope that ChatGPT will become more and more powerful and help more quantitative trading beginners get started easily.&lt;br /&gt;&lt;br /&gt;I hope that there will no longer be &amp;quot;from getting started to giving up&amp;quot; in the study of quantitative trading in the future!&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y6yuYBqnby0wCwm0sWpa8ys49HOGHbgnKjK66P9eetdPBWmz50gu4b4rxJ6rut0v7W0B1aFfEWzj8SlkCOs3No1PqkBk9tJA9d69QR_N_sKPAeF9uG89xNYvITu8hXdhdNgD3eYzhFk9-EEaLJOk0ZtY" title="https://blog.mathquant.com/2023/02/08/when-fmz-encounters-chatgpt-an-attempt-to-use-ai-to-assist-in-learning-quantitative-trading.html"&gt;https://blog.mathquant.c...uantitative-trading.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25701/</id>
    <title type="text">Elegant and simple! Accessed Uniswap V3 on FMZ with 200 lines of code</title>
    <published>2024-04-17T06:31:43Z</published>
    <updated>2024-04-17T06:31:43Z</updated>
    <author>
      <name>Trading</name>
      <uri>https://stocksharp.com/users/186421/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#code" />
    <category term="#market" />
    <category term="#contract" />
    <category term="#exchange" />
    <category term="#FMZQuant" />
    <category term="#uniswapV3" />
    <category term="#token" />
    <category term="#address" />
    <content type="html">With the popularity of Defi concept in recent years, Uniswap V3 is one of the most popular topics in the field of decentralized finance (DeFi). As a leading decentralized swap protocol, Uniswap V3 provides a more efficient, safer and better user experience. Now, with only 200 lines of code, traders and developers can access Uniswap V3 on the FMZ platform easily.&lt;br /&gt;&lt;br /&gt;FMZ is a quantitative trading platform that supports the development, backtesting and real market deployment of quantitative trading strategies. Its easy-to-use interface and powerful functions are not difficult to understand why FMZ is becoming the first choice of DeFi traders and developers.&lt;br /&gt;&lt;br /&gt;The process of integrating Uniswap V3 into FMZ is simple and easy to understand, requiring only 200 lines of code to complete. This means that even if you are new to code, you can easily connect to Uniswap V3 on FMZ and start trading immediately.&lt;br /&gt;&lt;br /&gt;FMZ has encapsulated a series of web3 basic functions. Besides Uniswap, it can also encapsulate other DEX exchanges with few codes. Next, let me take you to learn the concepts and technologies in defi application from scratch. Due to the space, the following description is as simple as possible. It may not be very precise, but it is easy to understand.&lt;br /&gt;&lt;br /&gt;[Uniswap V3 Trade Template](https://www.fmz.com/strategy/397260) disclosed by FMZ platform&lt;br /&gt;&lt;br /&gt;The code is as follows:&lt;br /&gt;```&lt;br /&gt;/* jshint esversion: 7 */&lt;br /&gt;&lt;br /&gt;const ABI_Route = &amp;#39;[{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;_factoryV2&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;factoryV3&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;_positionManager&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;_WETH9&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;constructor&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;WETH9&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approveMax&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approveMaxMinusOne&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approveZeroThenMax&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approveZeroThenMaxMinusOne&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;callPositionManager&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;result&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;paths&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint128[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amounts&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint128[]&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;maximumTickDivergence&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;secondsAgo&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;checkOracleSlippage&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;maximumTickDivergence&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;secondsAgo&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;checkOracleSlippage&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOutMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IV3SwapRouter.ExactInputParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;exactInput&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;fee&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOutMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint160&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;sqrtPriceLimitX96&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint160&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IV3SwapRouter.ExactInputSingleParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;exactInputSingle&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountInMaximum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IV3SwapRouter.ExactOutputParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;exactOutput&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;fee&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountInMaximum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint160&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;sqrtPriceLimitX96&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint160&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IV3SwapRouter.ExactOutputSingleParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;exactOutputSingle&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;factory&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;factoryV2&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;getApprovalType&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;enum IApproveAndCall.ApprovalType&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token0&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token1&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenId&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount0Min&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount1Min&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IApproveAndCall.IncreaseLiquidityParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;increaseLiquidity&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;result&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token0&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token1&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;fee&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;int24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tickLower&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;int24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;int24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tickUpper&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;int24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount0Min&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount1Min&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IApproveAndCall.MintParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;mint&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;result&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;previousBlockhash&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;multicall&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;deadline&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;multicall&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;multicall&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;results&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;positionManager&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;pull&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;refundETH&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;deadline&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint8&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;selfPermit&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;nonce&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;expiry&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint8&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;selfPermitAllowed&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;nonce&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;expiry&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint8&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;selfPermitAllowedIfNecessary&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;deadline&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint8&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;selfPermitIfNecessary&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOutMin&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address[]&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;to&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;swapExactTokensForTokens&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountInMax&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address[]&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;to&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;swapTokensForExactTokens&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;sweepToken&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;sweepToken&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeBips&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeRecipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;sweepTokenWithFee&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeBips&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeRecipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;sweepTokenWithFee&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;int256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount0Delta&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;int256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;int256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount1Delta&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;int256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;_data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;uniswapV3SwapCallback&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;unwrapWETH9&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;unwrapWETH9&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeBips&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeRecipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;unwrapWETH9WithFee&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeBips&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeRecipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;unwrapWETH9WithFee&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;wrapETH&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;receive&amp;quot;}]&amp;#39;;&lt;br /&gt;const ABI_Pool = &amp;#39;[{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;constructor\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;owner\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickLower\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickUpper\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;Burn\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;owner\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickLower\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickUpper\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;Collect\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sender\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;CollectProtocol\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sender\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;paid0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;paid1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;Flash\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint16\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;observationCardinalityNextOld\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint16\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint16\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;observationCardinalityNextNew\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint16\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;IncreaseObservationCardinalityNext\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sqrtPriceX96\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tick\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;Initialize\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sender\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;owner\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickLower\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickUpper\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;Mint\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint8\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeProtocol0Old\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint8\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint8\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeProtocol1Old\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint8\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint8\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeProtocol0New\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint8\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint8\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeProtocol1New\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint8\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;SetFeeProtocol\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sender\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int256\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int256\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sqrtPriceX96\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;liquidity\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tick\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;Swap\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickLower\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickUpper\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;burn\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickLower\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickUpper\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0Requested\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1Requested\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;collect\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0Requested\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1Requested\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;collectProtocol\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;factory\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;fee\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint24\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;feeGrowthGlobal0X128\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;feeGrowthGlobal1X128\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;bytes\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;data\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;bytes\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;flash\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint16\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;observationCardinalityNext\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint16\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;increaseObservationCardinalityNext\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sqrtPriceX96\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;initialize\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;liquidity\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;maxLiquidityPerTick\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickLower\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickUpper\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;bytes\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;data\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;bytes\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;mint\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;observations\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint32\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;blockTimestamp\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint32\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int56\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickCumulative\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int56\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;secondsPerLiquidityCumulativeX128\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;bool\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;initialized\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;bool\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint32[]\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;secondsAgos\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint32[]\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;observe\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int56[]\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickCumulatives\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int56[]\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160[]\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;secondsPerLiquidityCumulativeX128s\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160[]\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;bytes32\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;bytes32\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;positions\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;liquidity\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeGrowthInside0LastX128\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeGrowthInside1LastX128\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tokensOwed0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tokensOwed1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;protocolFees\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;token0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;token1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint8\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeProtocol0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint8\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint8\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeProtocol1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint8\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;setFeeProtocol\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;slot0\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sqrtPriceX96\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tick\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint16\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;observationIndex\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint16\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint16\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;observationCardinality\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint16\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint16\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;observationCardinalityNext\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint16\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint8\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeProtocol\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint8\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;bool\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;unlocked\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;bool\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickLower\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickUpper\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;snapshotCumulativesInside\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int56\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickCumulativeInside\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int56\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;secondsPerLiquidityInsideX128\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint32\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;secondsInside\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint32\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;recipient\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;bool\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;zeroForOne\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;bool\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amountSpecified\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;sqrtPriceLimitX96\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;bytes\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;data\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;bytes\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;swap\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;amount1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int256\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int16\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int16\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;tickBitmap\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;tickSpacing\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;ticks\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;liquidityGross\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int128\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;liquidityNet\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int128\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeGrowthOutside0X128\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint256\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;feeGrowthOutside1X128\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint256\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int56\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickCumulativeOutside\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int56\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint160\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;secondsPerLiquidityOutsideX128\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint160\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint32\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;secondsOutside\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint32\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;bool\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;initialized\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;bool\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;token0\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;token1\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;}]&amp;#39;&lt;br /&gt;const ABI_Factory = &amp;#39;[{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;constructor\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;fee\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickSpacing\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;FeeAmountEnabled\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;oldOwner\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;newOwner\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;OwnerChanged\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;anonymous\&amp;quot;:false,\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;token0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;token1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:true,\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;fee\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickSpacing\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;},{\&amp;quot;indexed\&amp;quot;:false,\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;pool\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;PoolCreated\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;event\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tokenA\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tokenB\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;fee\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;createPool\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;pool\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;fee\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickSpacing\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;enableFeeAmount\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;feeAmountTickSpacing\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint24\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;getPool\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;owner\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;name\&amp;quot;:\&amp;quot;parameters\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;factory\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;token0\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;token1\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;uint24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;fee\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;uint24\&amp;quot;},{\&amp;quot;internalType\&amp;quot;:\&amp;quot;int24\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;tickSpacing\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;int24\&amp;quot;}],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;view\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;},{\&amp;quot;inputs\&amp;quot;:[{\&amp;quot;internalType\&amp;quot;:\&amp;quot;address\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;_owner\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;address\&amp;quot;}],\&amp;quot;name\&amp;quot;:\&amp;quot;setOwner\&amp;quot;,\&amp;quot;outputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable\&amp;quot;,\&amp;quot;type\&amp;quot;:\&amp;quot;function\&amp;quot;}]&amp;#39;&lt;br /&gt;&lt;br /&gt;let ContractV3Factory = &amp;quot;0x1F98431c8aD98523631AE4a59f267346ea31F984&amp;quot;&lt;br /&gt;let ContractV3SwapRouterV2 = &amp;quot;0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45&amp;quot;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {&lt;br /&gt;    [decimals0, decimals1, sqrtPriceX96] = [decimals0, decimals1, sqrtPriceX96].map(BigInt);&lt;br /&gt;    const TWO = BigInt(2);&lt;br /&gt;    const TEN = BigInt(10);&lt;br /&gt;    const SIX_TENTH = BigInt(1000000);&lt;br /&gt;    const Q192 = (TWO ** BigInt(96)) ** TWO;&lt;br /&gt;    return (&lt;br /&gt;        Number((sqrtPriceX96 ** TWO * TEN ** decimals0 * SIX_TENTH) / (Q192 * TEN ** decimals1)) /&lt;br /&gt;        Number(SIX_TENTH)&lt;br /&gt;    );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function toAmount(s, decimals) {&lt;br /&gt;    return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function toInnerAmount(n, decimals) {&lt;br /&gt;    return (BigDecimal(n)*BigDecimal(Math.pow(10,decimals))).toFixed(0)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$.NewUniswapV3 = function(e) {&lt;br /&gt;    e = e || exchange&lt;br /&gt;    if (e.GetName() !== &amp;#39;Web3&amp;#39;) {&lt;br /&gt;        panic(&amp;quot;only support Web3 exchange&amp;quot;)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    let self = {&lt;br /&gt;        tokenInfo: {},&lt;br /&gt;        walletAddress: e.IO(&amp;quot;address&amp;quot;),&lt;br /&gt;        pool: {}&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // register&lt;br /&gt;    e.IO(&amp;quot;abi&amp;quot;, ContractV3Factory, ABI_Factory)&lt;br /&gt;    e.IO(&amp;quot;abi&amp;quot;, ContractV3SwapRouterV2, ABI_Route)&lt;br /&gt;&lt;br /&gt;    self.addToken = function(name, address) {&lt;br /&gt;        let ret = e.IO(&amp;quot;api&amp;quot;, address, &amp;quot;decimals&amp;quot;)&lt;br /&gt;        if (!ret) {&lt;br /&gt;            throw &amp;quot;get token decimals failed&amp;quot;&lt;br /&gt;        }&lt;br /&gt;        let decimals = Number(ret)&lt;br /&gt;        self.tokenInfo[name] = {&lt;br /&gt;            name: name,&lt;br /&gt;            decimals: decimals,&lt;br /&gt;            address: address&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    self.waitMined = function(tx) {&lt;br /&gt;        while (true) {&lt;br /&gt;            Sleep(1000)&lt;br /&gt;            let info = e.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getTransactionReceipt&amp;quot;, tx)&lt;br /&gt;            if (info &amp;amp;&amp;amp; info.gasUsed) {&lt;br /&gt;                return true&lt;br /&gt;            }&lt;br /&gt;            Log(&amp;#39;Transaction not yet mined&amp;#39;, tx)&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.swapToken = function(tokenIn, amountInDecimal, tokenOut, options) {&lt;br /&gt;        // options like {gasPrice: 11, gasLimit: 111, nonce: 111}&lt;br /&gt;        let tokenInInfo = self.tokenInfo[tokenIn]&lt;br /&gt;        let tokenOutInfo = self.tokenInfo[tokenOut]&lt;br /&gt;        if (!tokenInInfo) {&lt;br /&gt;            throw &amp;quot;not found token info &amp;quot; + tokenIn&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (!tokenOutInfo) {&lt;br /&gt;            throw &amp;quot;not found token info &amp;quot; + tokenOut&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        let amountIn = toInnerAmount(amountInDecimal, tokenInInfo.decimals)&lt;br /&gt;        let recipientAddress = self.walletAddress&lt;br /&gt;        if (tokenInInfo.name != &amp;#39;ETH&amp;#39;) {&lt;br /&gt;            let allowanceAmount = e.IO(&amp;quot;api&amp;quot;, tokenInInfo.address, &amp;quot;allowance&amp;quot;, self.walletAddress, ContractV3SwapRouterV2);&lt;br /&gt;            let realAmount = toAmount(allowanceAmount, tokenInInfo.decimals)&lt;br /&gt;            if (realAmount &amp;lt; toAmount(amountIn, tokenInInfo.decimals)) {&lt;br /&gt;                Log(&amp;quot;realAmount is&amp;quot;, realAmount, &amp;quot;too small, try to approve large amount&amp;quot;)&lt;br /&gt;                if (tokenInInfo.name == &amp;#39;USDT&amp;#39;) {&lt;br /&gt;                    // As described in Tether code: To change the approve amount you first have to reduce the addresses allowance to 0 calling approve(spender, 0)&lt;br /&gt;                    let txApprove = e.IO(&amp;quot;api&amp;quot;, tokenInInfo.address, &amp;quot;approve&amp;quot;, ContractV3SwapRouterV2, 0)&lt;br /&gt;                    if (!txApprove) {&lt;br /&gt;                        throw &amp;quot;approve error&amp;quot;&lt;br /&gt;                    }&lt;br /&gt;                    Log(&amp;quot;wait reduce approve&amp;quot;, txApprove)&lt;br /&gt;                    self.waitMined(txApprove)&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                let txApprove = e.IO(&amp;quot;api&amp;quot;, tokenInInfo.address, &amp;quot;approve&amp;quot;, ContractV3SwapRouterV2, &amp;#39;0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&amp;#39;);&lt;br /&gt;                if (!txApprove) {&lt;br /&gt;                    throw &amp;quot;approve error&amp;quot;&lt;br /&gt;                }&lt;br /&gt;                Log(&amp;quot;wait approve&amp;quot;, txApprove)&lt;br /&gt;                self.waitMined(txApprove)&lt;br /&gt;                Log(&amp;quot;approve success amountIn&amp;quot;, amountIn)&lt;br /&gt;            } else {&lt;br /&gt;                Log(&amp;quot;allowance&amp;quot;, realAmount, &amp;quot;no need to approve&amp;quot;)&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (tokenOutInfo.name == &amp;#39;ETH&amp;#39; || tokenOutInfo.address.toLowerCase() == &amp;#39;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;#39;) {&lt;br /&gt;            /*&lt;br /&gt;            ADDRESS_THIS &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAm4EpBUxTqxwMj9C_l9TjM6s_pti4WpvrTvDCglVxnmXq5ExsjjxaEjObr9baaHlrDNSzMYGugIICRudDKdXA6" title="https://degencode.substack.com/p/uniswapv3-multicall
"&gt;https://degencode.substa...m/p/uniswapv3-multicall
&lt;/a&gt;&lt;br /&gt;            &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAXfraG2_tjpF5qZhVa2DOPe32u3h5BBfr0slmn_B5xZ6rzN-eIwCZ8eLek5HxFvfxweQUD6mVbpx1Xvcf0CKfCYz-0zwKmUHA5rCm4GTxaKw" title="https://etherscan.io/address/0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45#code
"&gt;https://etherscan.io/add...85e0e4c7bd8665fc45#code
&lt;/a&gt;&lt;br /&gt;            */&lt;br /&gt;            recipientAddress = &amp;#39;0x0000000000000000000000000000000000000002&amp;#39;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        let swapToken = e.IO(&amp;quot;encode&amp;quot;, ContractV3SwapRouterV2, &amp;quot;swapExactTokensForTokens&amp;quot;, amountIn, 1, [tokenInInfo.address, tokenOutInfo.address], recipientAddress)&lt;br /&gt;        let data = [swapToken]&lt;br /&gt;        if (tokenOutInfo.name == &amp;#39;ETH&amp;#39;) {&lt;br /&gt;            data.push(e.IO(&amp;quot;encode&amp;quot;, ContractV3SwapRouterV2, &amp;quot;unwrapWETH9(uint256,address)&amp;quot;, 1, self.walletAddress))&lt;br /&gt;        }&lt;br /&gt;        let tx = e.IO(&amp;quot;api&amp;quot;, ContractV3SwapRouterV2, &amp;quot;multicall(uint256,bytes[])&amp;quot;, (tokenInInfo.name == &amp;#39;ETH&amp;#39; ? amountIn : 0), (new Date().getTime() / 1000) + 3600, data, options || {})&lt;br /&gt;        if (tx) {&lt;br /&gt;            Log(&amp;quot;tx: &amp;quot;, tx)&lt;br /&gt;            self.waitMined(tx)&lt;br /&gt;            Log(&amp;quot;swap&amp;quot;, tokenInInfo.name, &amp;quot;to&amp;quot;, tokenOutInfo.name, &amp;quot;success&amp;quot;)&lt;br /&gt;            return true&lt;br /&gt;        } else {&lt;br /&gt;            Log(&amp;quot;trans error&amp;quot;)&lt;br /&gt;            return false&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.getETHBalance = function(address) {&lt;br /&gt;        return toAmount(e.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getBalance&amp;quot;, address || self.walletAddress, &amp;quot;latest&amp;quot;), 18)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.balanceOf = function(token, address) {&lt;br /&gt;        let tokenInfo = self.tokenInfo[token]&lt;br /&gt;        if (!tokenInfo) {&lt;br /&gt;            throw &amp;quot;not found token info &amp;quot; + token&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return toAmount(e.IO(&amp;quot;api&amp;quot;, tokenInfo.address, &amp;quot;balanceOf&amp;quot;, address || self.walletAddress), tokenInfo.decimals)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.sendETH = function(to, amount, options) {&lt;br /&gt;        return e.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;send&amp;quot;, to, toInnerAmount(amount, 18), options || {})&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.getPrice = function(pair) {&lt;br /&gt;        let arr = pair.split(&amp;#39;_&amp;#39;)&lt;br /&gt;        let token0 = self.tokenInfo[arr[0]]&lt;br /&gt;        if (!token0) {&lt;br /&gt;            throw &amp;quot;token &amp;quot; + arr[0] + &amp;quot;not found&amp;quot;&lt;br /&gt;        }&lt;br /&gt;        let token1 = self.tokenInfo[arr[1]]&lt;br /&gt;        if (!token1) {&lt;br /&gt;            throw &amp;quot;token &amp;quot; + arr[1] + &amp;quot;not found&amp;quot;&lt;br /&gt;        }&lt;br /&gt;        let reverse = false&lt;br /&gt;        if (BigInt(token0.address) &amp;gt; BigInt(token1.address)) {&lt;br /&gt;            let tmp = token0&lt;br /&gt;            token0 = token1&lt;br /&gt;            token1 = tmp&lt;br /&gt;            reverse = true&lt;br /&gt;        }&lt;br /&gt;        let key = token0.address + &amp;#39;/&amp;#39; + token1.address&lt;br /&gt;        if (typeof(self.pool[key]) == &amp;#39;undefined&amp;#39;) {&lt;br /&gt;            let pool = e.IO(&amp;quot;api&amp;quot;, ContractV3Factory, &amp;quot;getPool&amp;quot;, token0.address, token1.address, 3000)&lt;br /&gt;            if (pool) {&lt;br /&gt;                self.pool[key] = pool&lt;br /&gt;                // register pool address&lt;br /&gt;                e.IO(&amp;quot;abi&amp;quot;, pool, ABI_Pool)&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        if (typeof(self.pool[key]) == &amp;#39;undefined&amp;#39;) {&lt;br /&gt;            throw &amp;quot;pool &amp;quot; + pair + &amp;quot; not found&amp;quot;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        let slot0 = e.IO(&amp;quot;api&amp;quot;, self.pool[key], &amp;quot;slot0&amp;quot;)&lt;br /&gt;&lt;br /&gt;        if (!slot0) {&lt;br /&gt;            return null&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        let price = computePoolPrice(token0.decimals, token1.decimals, slot0.sqrtPriceX96)&lt;br /&gt;        if (reverse) {&lt;br /&gt;            price = 1 / price&lt;br /&gt;        }&lt;br /&gt;        return price&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return self&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$.testUniswap = function() {&lt;br /&gt;    let ex = $.NewUniswapV3()&lt;br /&gt;    Log(&amp;quot;walletAddress: &amp;quot;, ex.walletAddress)&lt;br /&gt;    let tokenAddressMap = {&lt;br /&gt;        &amp;quot;ETH&amp;quot;: &amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;, // WETH&lt;br /&gt;        &amp;quot;USDT&amp;quot;: &amp;quot;0xdac17f958d2ee523a2206206994597c13d831ec7&amp;quot;,&lt;br /&gt;        &amp;quot;1INCH&amp;quot;: &amp;quot;0x111111111117dC0aa78b770fA6A738034120C302&amp;quot;,&lt;br /&gt;    }&lt;br /&gt;    for (let name in tokenAddressMap) {&lt;br /&gt;        ex.addToken(name, tokenAddressMap[name])&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    Log(ex.getPrice(&amp;#39;ETH_USDT&amp;#39;))&lt;br /&gt;    Log(ex.getPrice(&amp;#39;1INCH_USDT&amp;#39;))&lt;br /&gt;    // swap 0.01 ETH to USDT&lt;br /&gt;    Log(ex.swapToken(&amp;#39;ETH&amp;#39;, 0.01, &amp;#39;USDT&amp;#39;))&lt;br /&gt;    let usdtBalance = ex.balanceOf(&amp;#39;USDT&amp;#39;)&lt;br /&gt;    Log(&amp;quot;balance of USDT&amp;quot;, usdtBalance)&lt;br /&gt;    // swap reverse&lt;br /&gt;    Log(ex.swapToken(&amp;#39;USDT&amp;#39;, usdtBalance, &amp;#39;ETH&amp;#39;))&lt;br /&gt;    &lt;br /&gt;    Log(&amp;quot;balance of ETH&amp;quot;, ex.getETHBalance())&lt;br /&gt;    &lt;br /&gt;    // Log(ex.sendETH(&amp;#39;0x11111&amp;#39;, 0.02))&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;Ethereum network&lt;/b&gt;&lt;br /&gt;Ethereum network can be understood as a software infrastructure, on which various smart contracts can be deployed and run. Smart contracts have various functions and application scenarios. The devices running the Ethereum client constitute the nodes in the Ethereum network.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Some concepts in Uniswap V3&lt;/b&gt;&lt;br /&gt;Students who are not familiar with the ```Uniswap V3``` protocol need to understand a few concepts first. ```Uniswap V3``` is also a smart contract deployed and running on Ethereum.&lt;br /&gt;&lt;br /&gt;1. Route: Route is also a smart contract, which is used to manage the exchange of ```token```.&lt;br /&gt;2. Pool: The pool is also a smart contract for storing two kinds of Ethereum tokens and exchanging between these two tokens.&lt;br /&gt;3. Factory contract: A factory contract is a smart contract used to create a pool.&lt;br /&gt;4. ABI: (Application Binary Interface) is a specification that describes how smart contracts communicate with the outside world. It specifies the function name, parameter type and return value type of the smart contract, how to encode and decode data, and determines the external interface of the smart contract. It can be understood that to call an interface, it must be called according to the agreed standards of the interface, and the ABI records a series of agreed standards.&lt;br /&gt;&lt;br /&gt;Once the smart contract is deployed on Ethereum, there will be an address.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Analyze the code of Uniswap V3 Trade Template&lt;/b&gt;&lt;br /&gt;The Uniswap V3 trading class library code is mainly divided into four parts, which we will explain one by one.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Part 1: Constants used when interacting with Uniswap V3&lt;/em&gt;&lt;br /&gt;```&lt;br /&gt;const ABI_Route = &amp;#39;[{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address...&lt;br /&gt;const ABI_Pool = &amp;#39;[{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;nonpayable...&lt;br /&gt;const ABI_Factory = &amp;#39;[{\&amp;quot;inputs\&amp;quot;:[],\&amp;quot;stateMutability\&amp;quot;:\&amp;quot;...&lt;br /&gt;&lt;br /&gt;let ContractV3Factory = &amp;quot;0x1F98431c8aD98523631AE4a59f267346ea31F984&amp;quot;&lt;br /&gt;let ContractV3SwapRouterV2 = &amp;quot;0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45&amp;quot;&lt;br /&gt;```&lt;br /&gt;With the above basic concept preview, it&amp;#39;s easy to understand here.&lt;br /&gt;&lt;br /&gt;```ABI_Route``` The string stored by this constant is the ABI of the routing smart contract.&lt;br /&gt;```ABI_Pool``` stores the ABI of the pool contract.&lt;br /&gt;```ABI_Factory``` The ABI of the factory contract.&lt;br /&gt;&lt;br /&gt;Since these strings are long, they are just excerpts. These contents provide a standard for the program to call the smart contract method (for example, what are the parameters of the smart contract interface, how many parameters, what type are they, and what type of returned data are).&lt;br /&gt;&lt;br /&gt;As we mentioned just now, once the smart contract is deployed in Ethereum, there will be an address.&lt;br /&gt;&lt;br /&gt;```ContractV3Factory```: The address of the factory contract is recorded.&lt;br /&gt;```ContractV3SwapRouterV2```: The router V2 address of Uniswap V3. Note that Uniswap has V1 and V2. The router of Uniswap V3 also has V1 and V2. Different contract addresses are different.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Part2: Tool functions&lt;/em&gt;&lt;br /&gt;1. ```computePoolPrice``` function is used to calculate the price of the token in the pool.&lt;br /&gt;```&lt;br /&gt;function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {&lt;br /&gt;    [decimals0, decimals1, sqrtPriceX96] = [decimals0, decimals1, sqrtPriceX96].map(BigInt);   // Use the BigInt function for processing. Because of the precision of JavaScript language values, it is necessary to use one of FMZ&amp;#39;s underlying processing functions, BigInt, to process.&lt;br /&gt;    const TWO = BigInt(2);     // Define constant 2 to calculate&lt;br /&gt;    const TEN = BigInt(10);    // Define constant 10 to calculate&lt;br /&gt;    const SIX_TENTH = BigInt(1000000);    // Define the 6th power of constant 10, i.e. 1e6&lt;br /&gt;    const Q192 = (TWO ** BigInt(96)) ** TWO;  // 2^192&lt;br /&gt;    return (&lt;br /&gt;        Number((sqrtPriceX96 ** TWO * TEN ** decimals0 * SIX_TENTH) / (Q192 * TEN ** decimals1)) /&lt;br /&gt;        Number(SIX_TENTH)&lt;br /&gt;    );&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;If the trading pair is ```ETH_ USDT```, then ```token0``` is ```ETH```, and ```token1``` is ```USDT```. ```decimals0``` is the precision data of ```token0```, and ```decimals1``` is the precision data of ```token1```. ```SqrtPriceX96``` is the price-related data (not the direct price value), which can be obtained from the ```slot0``` method of the pool contract.&lt;br /&gt;&lt;br /&gt;sqrtPriceX96 : The current price of the pool as a sqrt(token1/token0) Q64.96 value&lt;br /&gt;Q64.96 is a data processing and storage standard.&lt;br /&gt;&lt;br /&gt;These three data ```decimals0```, ```decimals1```, ```sqrtPriceX96``` are passed into the ```computePoolPrice``` function as parameters to calculate the price of the trading pair ```ETH_USDT```. The algorithm in the last ```return``` statement of this function is the process of restoring ```sqrtPriceX96``` to ```token1/token0```. For example, the number of token0 (ETH) in the pool is 1, and the number of token1 (USDT) is 1100. So ```1100/1=1100```, the current price in the ```ETH_USDT``` pool is 1100.&lt;br /&gt;&lt;br /&gt;2. ```toAmount``` function is used to convert numeric data in the chain into readable data.&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;```&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;function toAmount(s, decimals) {&lt;br /&gt;    return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())&lt;br /&gt;}&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;```&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;To put it simply, for example, an ETH token is 1e18 when the number is represented on the chain, i.e., the 18th power of 10, because the precision data of ETH is 18. Not all tokens have a precision of 18, and the precision of USDT is not the same as that of ETH. The ```toAmount``` function is to convert 1e18 to 1.&lt;br /&gt;&lt;br /&gt;3. The ```toInnerAmount``` function is the opposite of the ```toAmount``` function, which converts readable data into values used in the chain.&lt;br /&gt;```&lt;br /&gt;function toInnerAmount(n, decimals) {&lt;br /&gt;    return (BigDecimal(n)*BigDecimal(Math.pow(10,decimals))).toFixed(0)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;Next, let&amp;#39;s analyze the code of &amp;quot;Uniswap V3 Trade Template&amp;quot;.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Part3: Constructor of Uniswap V3 operation object&lt;/em&gt;&lt;br /&gt;The core of this template class library is the Uniswap V3 operation object, which implements the basic operations on Uniswap V3. More functions may be upgraded in the future. By analyzing this code example, even if you do not use the FMZ platform, you will increase your knowledge and understanding of the processes and details of each link of Uniswap DEX. Now let&amp;#39;s learn how these basic functions are designed and implemented on FMZ.&lt;br /&gt;&lt;br /&gt;Constructor code of Uniswap V3 operation object:&lt;br /&gt;```&lt;br /&gt;$.NewUniswapV3 = function(e) {&lt;br /&gt;    e = e || exchange                          // If the parameter e is not passed, the exchange object exchange is used, that is, the first exchange added in the strategy.&lt;br /&gt;    if (e.GetName() !== &amp;#39;Web3&amp;#39;) {              // Determine if the exchange object is Web3, because this template only supports Web3 exchange objects.&lt;br /&gt;        panic(&amp;quot;only support Web3 exchange&amp;quot;)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    let self = {                               // The current function is a constructor, and the constructed object is the object self.&lt;br /&gt;        tokenInfo: {},                         // Member variable of the self object, used to record the registration information of the token.&lt;br /&gt;        walletAddress: e.IO(&amp;quot;address&amp;quot;),        // Record the address of the wallet to which the current exchange object is bound.&lt;br /&gt;        pool: {}                               // Used to record registered pool information.&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // register&lt;br /&gt;    e.IO(&amp;quot;abi&amp;quot;, ContractV3Factory, ABI_Factory)       // ABI for registered factory contracts&lt;br /&gt;    e.IO(&amp;quot;abi&amp;quot;, ContractV3SwapRouterV2, ABI_Route)    // ABI for registered routing contracts&lt;br /&gt;&lt;br /&gt;    self.addToken = function(name, address) {         // Used to register token&lt;br /&gt;        let ret = e.IO(&amp;quot;api&amp;quot;, address, &amp;quot;decimals&amp;quot;)    // Call the decimals method to get token precision information&lt;br /&gt;        if (!ret) {&lt;br /&gt;            throw &amp;quot;get token decimals failed&amp;quot;&lt;br /&gt;        }&lt;br /&gt;        let decimals = Number(ret)&lt;br /&gt;        self.tokenInfo[name] = {&lt;br /&gt;            name: name,&lt;br /&gt;            decimals: decimals,&lt;br /&gt;            address: address&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    self.waitMined = function(tx) {             // It is used to wait for the result of an operation on Ethereum. The hash is a tx parameter.&lt;br /&gt;        while (true) {&lt;br /&gt;            Sleep(1000)&lt;br /&gt;            let info = e.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getTransactionReceipt&amp;quot;, tx)  // Query results using eth_getTransactionReceipt method, if it&amp;#39;s not found, loop to continue query.&lt;br /&gt;            if (info &amp;amp;&amp;amp; info.gasUsed) {&lt;br /&gt;                return true&lt;br /&gt;            }&lt;br /&gt;            Log(&amp;#39;Transaction not yet mined&amp;#39;, tx)&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.swapToken = function(tokenIn, amountInDecimal, tokenOut, options) {   // For token exchange&lt;br /&gt;        // options like {gasPrice: 11, gasLimit: 111, nonce: 111}&lt;br /&gt;        let tokenInInfo = self.tokenInfo[tokenIn]      // Get the information of the exchanged token&lt;br /&gt;        let tokenOutInfo = self.tokenInfo[tokenOut]    // Get the information of the converted token&lt;br /&gt;        if (!tokenInInfo) {&lt;br /&gt;            throw &amp;quot;not found token info &amp;quot; + tokenIn&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (!tokenOutInfo) {&lt;br /&gt;            throw &amp;quot;not found token info &amp;quot; + tokenOut&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        let amountIn = toInnerAmount(amountInDecimal, tokenInInfo.decimals)  // Convert to data used on smart contracts&lt;br /&gt;        let recipientAddress = self.walletAddress&lt;br /&gt;        if (tokenInInfo.name != &amp;#39;ETH&amp;#39;) {&lt;br /&gt;            let allowanceAmount = e.IO(&amp;quot;api&amp;quot;, tokenInInfo.address, &amp;quot;allowance&amp;quot;, self.walletAddress, ContractV3SwapRouterV2);   // Query the number of authorizations&lt;br /&gt;            let realAmount = toAmount(allowanceAmount, tokenInInfo.decimals)&lt;br /&gt;            if (realAmount &amp;lt; toAmount(amountIn, tokenInInfo.decimals)) {    // If the number of licenses is insufficient&lt;br /&gt;                Log(&amp;quot;realAmount is&amp;quot;, realAmount, &amp;quot;too small, try to approve large amount&amp;quot;)&lt;br /&gt;                if (tokenInInfo.name == &amp;#39;USDT&amp;#39;) {&lt;br /&gt;                    // As described in Tether code: To change the approve amount you first have to reduce the addresses allowance to 0 calling approve(spender, 0)&lt;br /&gt;                    let txApprove = e.IO(&amp;quot;api&amp;quot;, tokenInInfo.address, &amp;quot;approve&amp;quot;, ContractV3SwapRouterV2, 0)  // If the authorized token is USDT, it needs to be authorized to 0 first.&lt;br /&gt;                    if (!txApprove) {&lt;br /&gt;                        throw &amp;quot;approve error&amp;quot;&lt;br /&gt;                    }&lt;br /&gt;                    Log(&amp;quot;wait reduce approve&amp;quot;, txApprove)&lt;br /&gt;                    self.waitMined(txApprove)&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                let txApprove = e.IO(&amp;quot;api&amp;quot;, tokenInInfo.address, &amp;quot;approve&amp;quot;, ContractV3SwapRouterV2, &amp;#39;0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&amp;#39;);  // Authorize Router contracts to operate the wallet&amp;#39;s tokens&lt;br /&gt;                if (!txApprove) {&lt;br /&gt;                    throw &amp;quot;approve error&amp;quot;&lt;br /&gt;                }&lt;br /&gt;                Log(&amp;quot;wait approve&amp;quot;, txApprove)&lt;br /&gt;                self.waitMined(txApprove)&lt;br /&gt;                Log(&amp;quot;approve success amountIn&amp;quot;, amountIn)&lt;br /&gt;            } else {&lt;br /&gt;                Log(&amp;quot;allowance&amp;quot;, realAmount, &amp;quot;no need to approve&amp;quot;)&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (tokenOutInfo.name == &amp;#39;ETH&amp;#39; || tokenOutInfo.address.toLowerCase() == &amp;#39;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;#39;) {&lt;br /&gt;            /*&lt;br /&gt;            ADDRESS_THIS &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAm4EpBUxTqxwMj9C_l9TjM6s_pti4WpvrTvDCglVxnmXq5ExsjjxaEjObr9baaHlrDNSzMYGugIICRudDKdXA6" title="https://degencode.substack.com/p/uniswapv3-multicall
"&gt;https://degencode.substa...m/p/uniswapv3-multicall
&lt;/a&gt;&lt;br /&gt;            &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAXfraG2_tjpF5qZhVa2DOPe32u3h5BBfr0slmn_B5xZ6rzN-eIwCZ8eLek5HxFvfxweQUD6mVbpx1Xvcf0CKfCYz-0zwKmUHA5rCm4GTxaKw" title="https://etherscan.io/address/0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45#code
"&gt;https://etherscan.io/add...85e0e4c7bd8665fc45#code
&lt;/a&gt;&lt;br /&gt;            */&lt;br /&gt;            recipientAddress = &amp;#39;0x0000000000000000000000000000000000000002&amp;#39;&lt;br /&gt;            // When exchanging other coins for WETH, you have to let the contract hold WETH before you can redeem it.&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        let swapToken = e.IO(&amp;quot;pack&amp;quot;, ContractV3SwapRouterV2, &amp;quot;swapExactTokensForTokens&amp;quot;, amountIn, 1, [tokenInInfo.address, tokenOutInfo.address], recipientAddress)   // Packaged swapExactTokensForTokens to call.&lt;br /&gt;        let data = [swapToken]&lt;br /&gt;        if (tokenOutInfo.name == &amp;#39;ETH&amp;#39;) {    // If the token exchanged back is ETH, which in this case is actually WETH, then it needs to unpack.&lt;br /&gt;            data.push(e.IO(&amp;quot;pack&amp;quot;, ContractV3SwapRouterV2, &amp;quot;unwrapWETH9(uint256,address)&amp;quot;, 1, self.walletAddress))   // So here is another unwrapWETH9 unpacking to call&lt;br /&gt;        }&lt;br /&gt;        let tx = e.IO(&amp;quot;api&amp;quot;, ContractV3SwapRouterV2, &amp;quot;multicall(uint256,bytes[])&amp;quot;, (tokenInInfo.name == &amp;#39;ETH&amp;#39; ? amountIn : 0), (new Date().getTime() / 1000) + 3600, data, options || {})   // Use multicall to perform these packaged operations (swapExactTokensForTokens, unwrapWETH9)&lt;br /&gt;        if (tx) {&lt;br /&gt;            Log(&amp;quot;tx: &amp;quot;, tx)&lt;br /&gt;            self.waitMined(tx)&lt;br /&gt;            Log(&amp;quot;swap&amp;quot;, tokenInInfo.name, &amp;quot;to&amp;quot;, tokenOutInfo.name, &amp;quot;success&amp;quot;)&lt;br /&gt;            return true&lt;br /&gt;        } else {&lt;br /&gt;            Log(&amp;quot;trans error&amp;quot;)&lt;br /&gt;            return false&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.getETHBalance = function(address) {   // Check your wallet&amp;#39;s ETH balance&lt;br /&gt;        return toAmount(e.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getBalance&amp;quot;, address || self.walletAddress, &amp;quot;latest&amp;quot;), 18)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.balanceOf = function(token, address) {  // Query the balance of a token in a wallet (determined by parameters)&lt;br /&gt;        let tokenInfo = self.tokenInfo[token]&lt;br /&gt;        if (!tokenInfo) {&lt;br /&gt;            throw &amp;quot;not found token info &amp;quot; + token&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return toAmount(e.IO(&amp;quot;api&amp;quot;, tokenInfo.address, &amp;quot;balanceOf&amp;quot;, address || self.walletAddress), tokenInfo.decimals)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.sendETH = function(to, amount, options) {   // Sending ETH tokens to an address, i.e. transfer&lt;br /&gt;        return e.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;send&amp;quot;, to, toInnerAmount(amount, 18), options || {})&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    self.getPrice = function(pair, fee) {     // Get price of trading pair&lt;br /&gt;        let arr = pair.split(&amp;#39;_&amp;#39;)&lt;br /&gt;        let token0 = self.tokenInfo[arr[0]]&lt;br /&gt;        if (!token0) {&lt;br /&gt;            throw &amp;quot;token &amp;quot; + arr[0] + &amp;quot;not found&amp;quot;&lt;br /&gt;        }&lt;br /&gt;        let token1 = self.tokenInfo[arr[1]]    // First, get the two token information that constitute the trading pair&lt;br /&gt;        if (!token1) {&lt;br /&gt;            throw &amp;quot;token &amp;quot; + arr[1] + &amp;quot;not found&amp;quot;&lt;br /&gt;        }&lt;br /&gt;        let reverse = false&lt;br /&gt;        if (BigInt(token0.address) &amp;gt; BigInt(token1.address)) {&lt;br /&gt;            let tmp = token0&lt;br /&gt;            token0 = token1&lt;br /&gt;            token1 = tmp&lt;br /&gt;            reverse = true&lt;br /&gt;        }&lt;br /&gt;        let key = token0.address + &amp;#39;/&amp;#39; + token1.address&lt;br /&gt;        if (typeof(self.pool[key]) == &amp;#39;undefined&amp;#39;) {&lt;br /&gt;            let pool = e.IO(&amp;quot;api&amp;quot;, ContractV3Factory, &amp;quot;getPool&amp;quot;, token0.address, token1.address, typeof(fee) === &amp;#39;number&amp;#39; ? fee : 3000)   // Call the getPool method of the factory contract to obtain the address of the exchange pool&lt;br /&gt;            if (pool) {&lt;br /&gt;                self.pool[key] = pool    // Register the pool address and register the ABI of the pool contract&lt;br /&gt;                // register pool address&lt;br /&gt;                e.IO(&amp;quot;abi&amp;quot;, pool, ABI_Pool)&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        if (typeof(self.pool[key]) == &amp;#39;undefined&amp;#39;) {&lt;br /&gt;            throw &amp;quot;pool &amp;quot; + pair + &amp;quot; not found&amp;quot;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        let slot0 = e.IO(&amp;quot;api&amp;quot;, self.pool[key], &amp;quot;slot0&amp;quot;)  // Call the slot0 method of the pool contract to get price related information&lt;br /&gt;&lt;br /&gt;        if (!slot0) {&lt;br /&gt;            return null&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        let price = computePoolPrice(token0.decimals, token1.decimals, slot0.sqrtPriceX96)  // Calculate the readable price&lt;br /&gt;        if (reverse) {&lt;br /&gt;            price = 1 / price&lt;br /&gt;        }&lt;br /&gt;        return price&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return self&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;Students who may be not familiar with FMZ see the function ```$.NewUniswapV3``` has a strange name. Functions with ```$``` at the beginning indicates that this function is the interface function of the template class library on FMZ (what is the template class library can be [viewed](https://www.fmz.com/api#template - library), simply put, the ```$. NewUniswapV3``` function can be called by other strategies that reference the **template class library** directly. The strategy has the function of ```Uniswap V3``` directly.&lt;br /&gt;&lt;br /&gt;The function ```$.NewUniswapV3``` directly constructs and creates an object, which can be used to perform some operations:&lt;br /&gt;&lt;br /&gt;- Token exchange: implemented by the ```swapToken``` method of the object.&lt;br /&gt;- ETH balance query: implemented by the ```getETHBalance``` method of the object.&lt;br /&gt;- Token balance query: implemented by the ```balanceOf``` method of the object.&lt;br /&gt;- Transaction pair price query: implemented by the ```getPrice``` method of the object.&lt;br /&gt;- Send ETH for transfer: implemented by the ```sendETH``` method of the object.&lt;br /&gt;&lt;br /&gt;This class library may not be limited to these functions in the future, and may even upgrade and add &amp;quot;add liquidity&amp;quot; and other functions. Let&amp;#39;s continue to analyze the code:&lt;br /&gt;```&lt;br /&gt;    e = e || exchange&lt;br /&gt;    if (e.GetName() !== &amp;#39;Web3&amp;#39;) {&lt;br /&gt;        panic(&amp;quot;only support Web3 exchange&amp;quot;)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    let self = {&lt;br /&gt;        tokenInfo: {},&lt;br /&gt;        walletAddress: e.IO(&amp;quot;address&amp;quot;),&lt;br /&gt;        pool: {}&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // register&lt;br /&gt;    e.IO(&amp;quot;abi&amp;quot;, ContractV3Factory, ABI_Factory)&lt;br /&gt;    e.IO(&amp;quot;abi&amp;quot;, ContractV3SwapRouterV2, ABI_Route)&lt;br /&gt;```&lt;br /&gt;The constructor ```$.NewUniswapV3``` has only one parameter ```e```, which means the exchange object (the exchange configuration on FMZ). Because the strategy on FMZ can be designed to be multi-exchange, so if a specific exchange is passed here, it means that the ```Uniswap V3``` object created is the one that operates the exchange object. If the parameter ```e``` is not passed, the first added exchange object is operated by default.&lt;br /&gt;&lt;br /&gt;Configure the node service address, private key (you can deploy the private key locally, local deployment only uses the configuration path), and an exchange object is created. It can be added to the strategy at the time of the real market, this object is reflected in the strategy code is ```exchange``` also known as ```exchanges[0]```, if you add the second, it&amp;#39;s ```exchanges[1]```, add the third for ```exchanges[2]```, ...&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150335
" title="https://stocksharp.com/file/150335
"&gt;https://stocksharp.com/file/150335
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The node address I configured in the screenshot: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAACtc0SYxwKqMws34TsGxEYlOYrhaFko3WvcRg8_ysyJH6FI7yPeJh7tkaLWzHRx5XM" title="https://mainnet.infura.io/v3/xxx, "&gt;https://mainnet.infura.io/v3/xxx, &lt;/a&gt;which is an infura node, which can be applied by individuals. Each account has its own specific address. xxx here is the mask, and the xxx part of each account is different.&lt;br /&gt;&lt;br /&gt;Continue with the code. The constructor starts to determine whether the exchange object is Web3, if not, an error will be reported. Then a variable ```self``` is created. The self is the object finally returned by the constructor. Subsequent constructors add various functions to this object and implement specific functions. The variable self has three attributes:&lt;br /&gt;&lt;br /&gt;- tokenInfo: records the token information registered in the object, including token address, token precision, and token name.&lt;br /&gt;- walletAddress: the wallet address of the current exchange object.&lt;br /&gt;- pool: the exchange pool information registered in the object, mainly including the name and address of the exchange pool.&lt;br /&gt;&lt;br /&gt;Then we use the concept we learned in the previous chapter:&lt;br /&gt;```&lt;br /&gt;e.IO(&amp;quot;abi&amp;quot;, ContractV3Factory, ABI_Factory)     // Register ABI for Uniswap V3 factory contract&lt;br /&gt;e.IO(&amp;quot;abi&amp;quot;, ContractV3SwapRouterV2, ABI_Route)  // Register ABI for Uniswap Router V2 routing &lt;br /&gt;```&lt;br /&gt;Why register this interface information?&lt;br /&gt;&lt;br /&gt;Because some functions to be implemented in the future need to call the interfaces of these smart contracts. Next, the constructor adds various methods to the self object. In addition to the above mentioned self object methods: exchange token, query balance, etc., there are also some tool functions belonging to the self object. Let&amp;#39;s analyze these tool functions first.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Tool functions for self objects&lt;/b&gt;&lt;br /&gt;1. ```self.addToken = function(name, address)```&lt;br /&gt;&lt;br /&gt;By observing the specific code of this function, we can see that this function is used to add (in other words, register) a token information to the current object ```self``` in the member ```tokenInfo``` that records ```token``` information. Because the precision data of ```token``` is often used in subsequent calculations, when this function adds (registers) token information, it calls the ```let ret=e.IO (&amp;quot;api&amp;quot;, address, &amp;quot;decimals&amp;quot;)``` function, and calls the ```&amp;quot;decimals&amp;quot;``` method of token contract through the FMZ encapsulated exchange.IO function (we mentioned that e is the exchange object passed in) to obtain the precision of token.&lt;br /&gt;&lt;br /&gt;So ```self. tokenInfo``` is a dictionary structure. Each key name is the token name, and the key value is the token information, including address, name, and precision. It looks like this:&lt;br /&gt;```&lt;br /&gt;{&lt;br /&gt;    &amp;quot;ETH&amp;quot;: {name: &amp;quot;ETH&amp;quot;, decimals: 18, address: &amp;quot;0x...&amp;quot;},&lt;br /&gt;    &amp;quot;USDT&amp;quot;: {name: &amp;quot;USDT&amp;quot;, decimals: 6, address: &amp;quot;0x...&amp;quot;},&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;2. ```self.waitMined = function(tx)```&lt;br /&gt;&lt;br /&gt;This function is used to wait for the execution result of the smart contract on Ethereum. From the implementation code of this function, we can see that this function has been calling ```let info=e.IO (&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getTransactionReceipt&amp;quot;, tx)``` in a loop. By calling the RPC method ```eth_ GetTransactionReceipt``` of Ethereum to query the transaction hash and return the transaction receipt. The parameter ```tx``` is the transaction hash.&lt;br /&gt;&lt;br /&gt;```eth_ GetTransactionReceipt``` and other relevant data can be viewed at: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAABlaJDx2jIW8Cm7K63Hv1s-0aK2glkK9qKTKcfQgoNb3B2o1yifuAZ-fjxWUo77b5Hb5TShdM5z5WHocST8QX2D14bclw6q_CemDFdbDDT47W8xP4PFkaNv76zEXAU849Q" title="https://ethereum.org/zh/developers/docs/apis/json-rpc/#eth_gettransactionreceipt
"&gt;https://ethereum.org/zh/...h_gettransactionreceipt
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Some students may ask: Why do we need this function?&lt;br /&gt;&lt;br /&gt;Answer: When performing some operations, such as token exchange, it is necessary to wait for the result.&lt;br /&gt;&lt;br /&gt;Next we will look at the other main functions of the object self created by the ```$.NewUniswapV3``` function, we start with the simplest one.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Main function functions&lt;/b&gt;&lt;br /&gt;1. ```self.getETHBalance = function(address)```&lt;br /&gt;&lt;br /&gt;The query of token balance can be divided into the query of ETH balance and the query of other ERC20 token balance. The getETHBalance function of the self object is used to query the ETH balance. When the specific wallet address parameter address is passed in, the ETH balance of this address is queried. If the address parameter is not passed, then the ETH balance of the ```self.walletAddress``` address (i.e. the wallet configured on the current exchange) is queried.&lt;br /&gt;&lt;br /&gt;If the address parameter is not passed, then the ETH balance of the ```self.walletAddress``` address (i.e. the wallet configured on the current exchange) is queried.&lt;br /&gt;&lt;br /&gt;These are achieved by calling the RPC method ```eth_getBalance``` of Ethereum.&lt;br /&gt;&lt;br /&gt;2. ```self.balanceOf = function(token, address)```&lt;br /&gt;&lt;br /&gt;To query the token balance other than ETH, you need to pass in the parameter token, that is, the token name, such as USDT. Pass in the address of the wallet to be queried, and if no address is passed in, query the balance of the address of ```self.walletAddress```. By observing the code implemented by this function, we can see that only the token registered through the ```self.addToken``` function can be queried, because the precision information and address of the token (token) are required when calling the ```balanceOf``` method of the token contract.&lt;br /&gt;&lt;br /&gt;3. ```self.sendETH = function(to, amount, options)```&lt;br /&gt;&lt;br /&gt;The function of this function is ETH transfer. To transfer a certain amount of ETH to a wallet address (using the parameter ```to``` to set), you can set another ```options``` parameter (data structure: ```{gasPrice: 111, gasLimit: 111, nonce: 111}```) to specify the ```gasLimit/gasPrice/once``` parameter. The system default setting is used without passing in the options parameter.&lt;br /&gt;&lt;br /&gt;```GasLimit/gasPrice``` affects the ETH consumed when performing operations on Ethereum (some operations on Ethereum consume gas, that is, certain ETH tokens).&lt;br /&gt;&lt;br /&gt;4. ```self.getPrice = function(pair, fee)```&lt;br /&gt;&lt;br /&gt;This function is used to obtain the price of a trading pair on Uniswap. You can see from the function implementation code that the trading pair will be parsed at the beginning of the function execution to obtain the baseCurrency and quoteCurrency. For example, the trading pair is ETH_USDT, it will be split into ETH and USDT. Then query whether there are two kinds of token information in ```self.tokenInfo```. If there is no information, an error will be reported.&lt;br /&gt;&lt;br /&gt;The exchange pool address on Uniswap is composed of two token addresses and Fee (rate standard) calculations. So when querying the pool address recorded in ```self. tool``` (we have mentioned self.tool before, you can check it), if not found, use the two token addresses and Fee to calculate the pool address. So a trading pair may have multiple pools, because the Fee may be different.&lt;br /&gt;&lt;br /&gt;The address of the query and calculation exchange pool is obtained by calling the ```getPool``` method of the factory contract in Uniswap V3 (so you need to register the ABI of the factory contract at the beginning).&lt;br /&gt;&lt;br /&gt;Get the pool address of the trading pair, and you can register the ABI of the pool contract. In this way, the ```slot0``` method of this pool (smart contract) can be called to get the price data. Of course, the data returned by this method is not a human-readable price, but a price-related data structure. Further processing is needed to obtain a readable price. At this time, we use the ```computePoolPrice``` function mentioned in the previous section.&lt;br /&gt;&lt;br /&gt;5. ```self.swapToken = function(tokenIn, amountInDecimal, tokenOut, options)```&lt;br /&gt;&lt;br /&gt;The function of this function is token exchange. The parameter tokenIn is the name of the token paid during exchange, the parameter tokenOut is the name of the token obtained during exchange, and the parameter amountInDecimal is the exchange quantity (human-readable quantity). The parameter options, as we mentioned earlier, can be set for gas consumption, nonce, etc. during exchange.&lt;br /&gt;&lt;br /&gt;When the function is executed, the information of token (token) is first obtained from the ```self. tokenInfo``` variable. There are many details of the exchange. First, if the token involved in the exchange is not ETH, then the **routing** (smart contract responsible for exchange) needs to be authorized first. Before authorization, check whether there is enough authorization.&lt;br /&gt;```&lt;br /&gt;let allowanceAmount = e.IO(&amp;quot;api&amp;quot;, tokenInInfo.address, &amp;quot;allowance&amp;quot;, self.walletAddress, ContractV3SwapRouterV2);&lt;br /&gt;```&lt;br /&gt;Use the token contract allowance method to query the authorized amount. By comparing the authorized amount with the current amount of exchange, if the authorized amount is enough to exchange, no authorization is needed. If the amount is insufficient, the authorization processing will be executed.&lt;br /&gt;&lt;br /&gt;There is also a detail of authorization here. If the authorized token is a USDT, you need to reset the number of authorization to 0 before authorization. The approve method of the token contract is authorized. Note that the approval authorization method is a gas consumption method, which will consume a certain amount of ETH. So you need to use the self.waitMined function to wait for the processing result.&lt;br /&gt;&lt;br /&gt;In order to avoid frequent authorization and pay unnecessary ETH, this authorization operation is the maximum one-time authorization.&lt;br /&gt;```&lt;br /&gt;let txApprove = e.IO(&amp;quot;api&amp;quot;, tokenInInfo.address, &amp;quot;approve&amp;quot;, ContractV3SwapRouterV2, &amp;#39;0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&amp;#39;);&lt;br /&gt;```&lt;br /&gt;With enough exchange limits, you can exchange. However, there are also details here. If the token involved in the exchange, the token obtained after the exchange is ETH, then you need to change the receiving address:&lt;br /&gt;```&lt;br /&gt;recipientAddress = &amp;#39;0x0000000000000000000000000000000000000002&amp;#39;&lt;br /&gt;```&lt;br /&gt;The specific reasons are more complex and are not described here, please refer to:&lt;br /&gt;&lt;br /&gt;ADDRESS_THIS &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAm4EpBUxTqxwMj9C_l9TjM6s_pti4WpvrTvDCglVxnmXq5ExsjjxaEjObr9baaHlrDNSzMYGugIICRudDKdXA6" title="https://degencode.substack.com/p/uniswapv3-multicall
"&gt;https://degencode.substa...m/p/uniswapv3-multicall
&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAXfraG2_tjpF5qZhVa2DOPe32u3h5BBfr0slmn_B5xZ6rzN-eIwCZ8eLek5HxFvfxweQUD6mVbpx1Xvcf0CKfCYz-0zwKmUHA5rCm4GTxaKw" title="https://etherscan.io/address/0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45#code
"&gt;https://etherscan.io/add...85e0e4c7bd8665fc45#code
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then use the packaging function ```e.IO(&amp;quot;pack&amp;quot;, ...```) encapsulated by the FMZ platform to package the swapExactTokensForTokens method call for routing (smart contract). If the token obtained after exchange is ETH, you need to add a step of WETH9 unpacking operation:&lt;br /&gt;```&lt;br /&gt;data.push(e.IO(&amp;quot;pack&amp;quot;, ContractV3SwapRouterV2, &amp;quot;unwrapWETH9(uint256,address)&amp;quot;, 1, self.walletAddress))&lt;br /&gt;```&lt;br /&gt;Because WETH is involved in the exchange. This is a packaged token of ETH. For real ETH, unpacking operation is required. After the unpacking operation is also packaged, the multicast method of routing (smart contract) can be called to perform this series of operations. Here is another detail to pay extra attention to: if the trading pair participating in the exchange, the payment token is ETH, the number of ETH transferred needs to be set in the following steps. If it is not ETH, set 0.&lt;br /&gt;```&lt;br /&gt;let tx = e.IO(&amp;quot;api&amp;quot;, ContractV3SwapRouterV2, &amp;quot;multicall(uint256,bytes[])&amp;quot;, (tokenInInfo.name == &amp;#39;ETH&amp;#39; ? amountIn : 0), (new Date().getTime() / 1000) + 3600, data, options || {})&lt;br /&gt;```&lt;br /&gt;The setting is reflected here: ```(tokenInInfo. name==&amp;#39;ETH &amp;#39;? AmountIn: 0)```. I did not make it clear before that I did not set 0 when tokenIn was not equal to ETH token, resulting in the wrong transfer of ETH. So be careful when writing the transfer code.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Part4: How to use Uniswap V3 operation objects&lt;/em&gt;&lt;br /&gt;The code in this template is actually less than 200 lines in terms of function implementation. The following paragraph is a demonstration of its use.&lt;br /&gt;```&lt;br /&gt;$.testUniswap = function() {&lt;br /&gt;    let ex = $.NewUniswapV3()&lt;br /&gt;    Log(&amp;quot;walletAddress: &amp;quot;, ex.walletAddress)&lt;br /&gt;    let tokenAddressMap = {&lt;br /&gt;        &amp;quot;ETH&amp;quot;: &amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;, // WETH&lt;br /&gt;        &amp;quot;USDT&amp;quot;: &amp;quot;0xdac17f958d2ee523a2206206994597c13d831ec7&amp;quot;,&lt;br /&gt;        &amp;quot;1INCH&amp;quot;: &amp;quot;0x111111111117dC0aa78b770fA6A738034120C302&amp;quot;,&lt;br /&gt;    }&lt;br /&gt;    for (let name in tokenAddressMap) {&lt;br /&gt;        ex.addToken(name, tokenAddressMap[name])&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    Log(ex.getPrice(&amp;#39;ETH_USDT&amp;#39;))&lt;br /&gt;    Log(ex.getPrice(&amp;#39;1INCH_USDT&amp;#39;))&lt;br /&gt;    // swap 0.01 ETH to USDT&lt;br /&gt;    Log(ex.swapToken(&amp;#39;ETH&amp;#39;, 0.01, &amp;#39;USDT&amp;#39;))&lt;br /&gt;    let usdtBalance = ex.balanceOf(&amp;#39;USDT&amp;#39;)&lt;br /&gt;    Log(&amp;quot;balance of USDT&amp;quot;, usdtBalance)&lt;br /&gt;    // swap reverse&lt;br /&gt;    Log(ex.swapToken(&amp;#39;USDT&amp;#39;, usdtBalance, &amp;#39;ETH&amp;#39;))&lt;br /&gt;    &lt;br /&gt;    Log(&amp;quot;balance of ETH&amp;quot;, ex.getETHBalance())&lt;br /&gt;    &lt;br /&gt;    // Log(ex.sendETH(&amp;#39;0x11111&amp;#39;, 0.02))&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;The function ```$. testUniswap=function()``` is only a demonstration. Do not call it without practical use. Let&amp;#39;s use this function to see how to use this template class library to operate the function of Uniswap V3.&lt;br /&gt;&lt;br /&gt;In the code, execute ```let ex=$. NewUniswapV3()``` to construct a Uniswap V3 operation object first. If you want to get the wallet address bound by the current exchange, you can use ```ex. walletAddress``` to get it. Then, the code uses the ```ex.addToken``` to register three kinds of tokens, namely ETH, USDT and 1INCH.&lt;br /&gt;&lt;br /&gt;Print the price of a trading pair (token needs to be registered first):&lt;br /&gt;```&lt;br /&gt;Log(ex.getPrice(&amp;#39;ETH_USDT&amp;#39;))&lt;br /&gt;Log(ex.getPrice(&amp;#39;1INCH_USDT&amp;#39;))&lt;br /&gt;```&lt;br /&gt;The getPrice function uses the default rate of 3,000 if no Fee is set, which is converted to a readable value of 0.3%.&lt;br /&gt;&lt;br /&gt;If you want to convert 0.01 ETH to USDT, then check the balance and then convert back, use the code:&lt;br /&gt;```&lt;br /&gt;Log(ex.swapToken(&amp;#39;ETH&amp;#39;, 0.01, &amp;#39;USDT&amp;#39;))&lt;br /&gt;&lt;br /&gt;let usdtBalance = ex.balanceOf(&amp;#39;USDT&amp;#39;)   // Check the balance of USDT after exchange&lt;br /&gt;Log(&amp;quot;balance of USDT&amp;quot;, usdtBalance)&lt;br /&gt;&lt;br /&gt;Log(ex.swapToken(&amp;#39;USDT&amp;#39;, usdtBalance, &amp;#39;ETH&amp;#39;))  // Exchange USDT to ETH&lt;br /&gt;Log(&amp;quot;balance of ETH&amp;quot;, ex.getETHBalance())      // Check ETH Balance&lt;br /&gt;&lt;br /&gt;// Log(ex.sendETH(&amp;#39;0x11111&amp;#39;, 0.02))            // ETH transfer operations&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;Testing with the test network Goerli&lt;/b&gt;&lt;br /&gt;1. Configure the test network exchange object&lt;br /&gt;&lt;br /&gt;Note that setting up the node requires setting up the node as a test network Goerli.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150336
" title="https://stocksharp.com/file/150336
"&gt;https://stocksharp.com/file/150336
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2. Write a strategy and test it on the test network Goerli.&lt;br /&gt;```&lt;br /&gt;function main() {&lt;br /&gt;    let ex = $.NewUniswapV3()&lt;br /&gt;    Log(&amp;quot;walletAddress: &amp;quot;, ex.walletAddress)&lt;br /&gt;    let tokenAddressMap = {&lt;br /&gt;        &amp;quot;ETH&amp;quot;  : &amp;quot;0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6&amp;quot;,  // WETH&lt;br /&gt;        &amp;quot;LINK&amp;quot; : &amp;quot;0x326C977E6efc84E512bB9C30f76E30c160eD06FB&amp;quot;,&lt;br /&gt;        &amp;quot;UNI&amp;quot;  : &amp;quot;0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984&amp;quot;,&lt;br /&gt;    }&lt;br /&gt;    for (let name in tokenAddressMap) {&lt;br /&gt;        ex.addToken(name, tokenAddressMap[name])&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // ETH_UNI 、 UNI_ETH&lt;br /&gt;    Log(&amp;quot;ETH_UNI:&amp;quot;, ex.getPrice(&amp;#39;ETH_UNI&amp;#39;))&lt;br /&gt;    Log(&amp;quot;UNI_ETH:&amp;quot;, ex.getPrice(&amp;#39;UNI_ETH&amp;#39;))&lt;br /&gt;    &lt;br /&gt;    // ETH &lt;br /&gt;    Log(&amp;quot;balance of ETH&amp;quot;, ex.getETHBalance())&lt;br /&gt;    &lt;br /&gt;    // UNI&lt;br /&gt;    let uniBalance = ex.balanceOf(&amp;#39;UNI&amp;#39;)&lt;br /&gt;    Log(&amp;quot;balance of UNI&amp;quot;, uniBalance)&lt;br /&gt;    &lt;br /&gt;    // LINK&lt;br /&gt;    let linkBalance = ex.balanceOf(&amp;#39;LINK&amp;#39;)&lt;br /&gt;    Log(&amp;quot;balance of LINK&amp;quot;, linkBalance)&lt;br /&gt;    &lt;br /&gt;    // swap 0.001 ETH to UNI&lt;br /&gt;    Log(ex.swapToken(&amp;#39;ETH&amp;#39;, 0.001, &amp;#39;UNI&amp;#39;))&lt;br /&gt;    &lt;br /&gt;    // swap UNI to LINK&lt;br /&gt;    Log(ex.swapToken(&amp;#39;UNI&amp;#39;, ex.balanceOf(&amp;#39;UNI&amp;#39;) - uniBalance, &amp;#39;LINK&amp;#39;))&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;In the test code, we tested the printing of wallet address, registration of token information, printing of asset balance, and a continuous exchange of ```ETH -&amp;gt;UNI -&amp;gt;LINK```. It should be noted that the token address registered here is on the Goorli test network of Ethereum, so the token address with the same name is different. As for the test token, you can use the faucet of this test network to apply for the test token, and the details can be queried by Google.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150337
" title="https://stocksharp.com/file/150337
"&gt;https://stocksharp.com/file/150337
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note that you must check the &amp;quot;Uniswap V3 Trade Template&amp;quot; to use the ```$. NewUniswapV3()``` function. If your FMZ account does not have this template, you can click [Get here](https://www.fmz.com/strategy/397260).&lt;br /&gt;&lt;br /&gt;Asset values displayed on the Uniswap page&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAC3KH9_yAE7OGJtvrYePtizAwOvVqVLEqo5jOz3PCLRyQ" title="https://app.uniswap.org/
"&gt;https://app.uniswap.org/
&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150339
" title="https://stocksharp.com/file/150339
"&gt;https://stocksharp.com/file/150339
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;These operations can also be queried in the chain:&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAACU7trfMmLxfYlhkikMz-uYmlUZPLdKu2f6O3bKJ77_Wg" title="https://goerli.etherscan.io/
"&gt;https://goerli.etherscan.io/
&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150341
" title="https://stocksharp.com/file/150341
"&gt;https://stocksharp.com/file/150341
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ETH was converted to UNI once, UNI authorization was executed once, and UNI was exchanged to LINK once.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;END&lt;/b&gt;&lt;br /&gt;There are many functions of this class library that can be extended, and can even be extended to package multiple exchanges to realize ```tokenA -&amp;gt;tokenB -&amp;gt;tokenC``` path exchange. It can be optimized and expanded according to the needs. This kind of library code is mainly for teaching.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update&lt;/b&gt;&lt;br /&gt;The ```swapToken``` function has been upgraded to support ```tokenA -&amp;gt;tokenB -&amp;gt;tokenC... -&amp;gt; TokenD``` continuous exchange function. You can check the latest code of the template published by Strategy Square on FMZ platform.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y6w5Y_yPk5fqeeMfM017zvUOazxN7_1MVvw1KyxjM_xDdIfXh_9yScBcsFMjapSVVpx4oRqeJS32zseXVe0oIsJASIZyx1SCx5lhE7PcC2vg4" title="https://blog.mathquant.com/2023/02/09/elegant-and-simple-accessed-uniswap-v3-on-fmz-with-200-lines-of-code.html"&gt;https://blog.mathquant.c...h-200-lines-of-code.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25700/</id>
    <title type="text">Build probability thinking to improve your trading pattern</title>
    <published>2024-04-17T05:09:12Z</published>
    <updated>2024-04-17T05:09:12Z</updated>
    <author>
      <name>Trading</name>
      <uri>https://stocksharp.com/users/186421/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#strategy" />
    <category term="#analysis" />
    <category term="#exchange" />
    <category term="#profit" />
    <category term="#FMZQuant" />
    <category term="#marekt" />
    <category term="#risks" />
    <category term="#returns" />
    <content type="html">&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;Trading is both a science and an art. There are many methods in trading, whether it is value investment, technical analysis, event hot spots, arbitrage hedging, etc., which seem logically rigorous on the surface, and it can also be plausible theoretically. But in fact, they often contradict each other. Sometimes, the rigor of science cannot explain the unconstrained nature of art.&lt;br /&gt;&lt;br /&gt;Although various trading methods have different starting points, all roads lead to Rome. The advantage of value investment is that it can divide a margin of safety for price fluctuations according to value; The advantage of technical analysis is that the three major assumptions make the transaction scientific.&lt;br /&gt;&lt;br /&gt;However, they all have a common feature, that is, the price analysis of the future can only be predicted roughly not accurately. Even if fundamental analysis and technical analysis are combined, the problem of improving &amp;quot;accuracy&amp;quot; cannot be solved, so trading is a probability game from beginning to end.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Probability game&lt;/b&gt;&lt;br /&gt;In fact, not only trading is a game of probability. When you cross the road (green light, is it safe to cross the road now?); What kind of friends do you make (is this friend reliable?); What kind of business you are engaged in (is career trading really a good business?), who you marry (will we be happy together?), and so on, are all probability games to evaluate risks and returns. Because we do not have the ability to predict, even if we are more confident about everything, risks always exist, and we cannot achieve 100% certainty.&lt;br /&gt;&lt;br /&gt;The important reason why many people make mistakes in trading is that they lack probability thinking and are too emotional rather than rational in trading. Sensibility is actually our primitive instincts. In the market, these primitive instincts can stimulate many weaknesses of people and magnify them exponentially. This is also the reason why most people come to the market and end up with failure.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Reasons for trading failure&lt;/b&gt;&lt;br /&gt;&lt;em&gt;Reason 1: Because of human nature&lt;/em&gt;&lt;br /&gt;Most people have one weakness: they like to take small advantages but they are afraid of small losses. Once there is a small profit in the market, they will immediately cash out, take profits out; Once there is a loss, they hold on to the loss position and try to get lucky to get back their capital. As a result, small losses accumulate into large losses gradually.&lt;br /&gt;&lt;br /&gt;The price will either go up or down, or it will not move. In the long run, the probability of making profits and losing money is about 50% without considering the handling fee and sliding point, so the trading method of most people will become a negative expectation strategy with limited profits and unlimited risks. Their transaction statements should be as follows: small profit &amp;gt;&amp;gt; ... &amp;gt;&amp;gt;small profit &amp;gt;&amp;gt;great loss.&lt;br /&gt;&lt;br /&gt;In real life, this is very similar to the thinking of the poor and the rich. The poor are risk-averse and afraid of loss, they like the work of ensuring harvest in drought and flood, and pursue stability. Even if they are not absolutely sure about doing something, they will never do it. On the surface, there seems to be nothing wrong with this, but there are huge opportunity risks behind it.&lt;br /&gt;&lt;br /&gt;The rich are more willing to take risks. They know that risks are always proportional to returns. Only risks breed opportunities. They can reasonably evaluate risks and make bold bets when risks are controllable.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Reason 2: Like to make quick money&lt;/em&gt;&lt;br /&gt;A foreign organization once made statistics. In the long run, the annualized return on net assets of most industries is difficult to exceed 15%. On the contrary, many retail investors think that they can earn 15% in the market and are embarrassed to say hello to others. People like to make fast money. In action, they are large position trading and short-term trading.&lt;br /&gt;&lt;br /&gt;Large position&lt;br /&gt;Large positions, high leverage and capital allocation are very attractive and dangerous. Success leads to success, and failure leads to disaster. If you have a trading strategy with a winning rate of 50%, and a full position plus matching operation, you may win more than ten times in a row if you are lucky. It is also possible for wealth to change from quantitative to qualitative.&lt;br /&gt;&lt;br /&gt;However, you only need to make a mistake once, and then you will return to zero. Even if you just take a large position without matching, there is a risk that your account will return to zero, because you cannot guarantee that you will lose more than ten times in the next market. Even large position trading can turn a trading strategy that was expected to be positive into a strategy that is not equal to winning or losing.&lt;br /&gt;&lt;br /&gt;Short-term&lt;br /&gt;In the trading world, manual order speculation, intra-day short-term trading and quantitative high-frequency trading have always been very mysterious. I am not suspicious of those who watch the stopwatch to trade, but try to persuade you to give up short-term trading from another perspective.&lt;br /&gt;&lt;br /&gt;We can judge whether a method is feasible, not only by those who succeed in these methods, but also by those who fail in these methods. In other words, you can&amp;#39;t think that buying lottery tickets is a positive strategy just because some people win the lottery.&lt;br /&gt;&lt;br /&gt;In addition, look at the list of private placement products. How many of the top 100 in the list for more than three years are engaged in speculation or short-term trading? There is no doubt that the rate of short-term production is very low. Even if it is successful, this method of making money quickly is difficult to maintain for a long time. If you are not gifted, be careful to use this kind of unique skill. After all, Simmons has only one.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Reason 3: Prejudice&lt;/em&gt;&lt;br /&gt;If you can, it is recommended that you spend 100 minutes watching a movie - &amp;quot;Twelve Angry Men&amp;quot;. A film remade by four countries, the first edition in the United States in 1957, the Japanese version in 1991, the Russian version in 1997, and the Chinese version in 2014. Although this film does not teach you how to do trading, it does teach you how to look at things and learn to know yourself, which is very important.&lt;br /&gt;&lt;br /&gt;Because human experience is limited, so is human cognition. Everyone is more or less biased according to their own experience. In many cases, prejudice has become the habit of most people, and it is natural to judge many things with their own emotions.&lt;br /&gt;&lt;br /&gt;Back to the market, whether your judgment of the market is based on fundamental analysis or technical analysis, these are not really important. If your point of view is different from that of the majority of the market, the price is more biased towards the majority of the market, and the market will not operate according to your point of view.&lt;br /&gt;&lt;br /&gt;Therefore, in the transaction, we must keep in mind &amp;quot;judgment, but not rely on judgment&amp;quot;. Ultimately, we should be based on facts and prices. The only strength of price rise and fall is the expectation of most people for the future. Your judgment has no weight in the market. Don&amp;#39;t let your judgment form your own prejudice.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Reason 4: Pursuit of perfection.&lt;/em&gt;&lt;br /&gt;Market participants include elites from all walks of life, including physics, statistics, mathematics, astronomy, etc. Many people try to explain the market with their professional knowledge.&lt;br /&gt;&lt;br /&gt;But the main body of market participation is people, and people themselves have cognitive limitations, which means that the market itself is wrong and imperfect. So how can we use these &amp;quot;perfect&amp;quot; methods to explain the market? Isn&amp;#39;t that against the nature of the market?&lt;br /&gt;&lt;br /&gt;The above lists the reasons why the vast majority of people who came to the market ended in failure. In addition to the main reasons mentioned above, there are many factors that will not be listed here. In short, in addition to your confidence in winning, everything else is a stumbling block to your success.&lt;br /&gt;&lt;br /&gt;Those who make profits in the market because of good luck will eventually give it back to the market as time goes by. Therefore, the futures market is a negative sum game market. Only by changing your own way of thinking and establishing your own trading strategy, can you succeed.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is the thinking mode of probability?&lt;/b&gt;&lt;br /&gt;Probabilistic thinking is a literary name. To put it more popular, it is gambling thinking. You heard me right. Trading is gambling. When you hear about gambling, you may think of &amp;quot;who gambles and loses his money or runs away in debt or splits his wife and children&amp;quot; and avoid it.&lt;br /&gt;&lt;br /&gt;There are also some red-eyed gamblers in society. But gambling ≠ gamblers. &amp;quot;Gambling&amp;quot; is probably one of the most misunderstood words. If your strategy is negative, you are a gambler; If your strategy is positive expectation, it is gambling.&lt;br /&gt;&lt;br /&gt;If we remove the derogatory meaning of &amp;quot;gambling&amp;quot; and understand it as an activity that takes certain risks and obtains certain rewards, then life is really &amp;quot;gambling&amp;quot; everywhere. Which major to choose in school, whether to buy a house, whether to start a project, whether to work or start a business, etc.&lt;br /&gt;&lt;br /&gt;Even saving money in a bank is also a gamble, because you are not sure whether inflation will occur in the future and whether the bank will go bankrupt (refer to the Greek debt crisis). In short, from cradle to grave, every process of life is gambling.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How to win gambling for a long time&lt;/b&gt;&lt;br /&gt;With the concept of gambling, we need to further solve it. How can we win at gambling for a long time? Before we study the strategy of &amp;quot;win at gambling for a long time&amp;quot;, let&amp;#39;s first study the principle of those strategies of &amp;quot;win at gambling for a long time&amp;quot;. In addition to the money printing machine, what else can we win at gambling for a long time?&lt;br /&gt;&lt;br /&gt;That&amp;#39;s what&amp;#39;s in the casino: baccarat, roulette, slot machine, blackjack, etc. No matter how you change the playing method, the casino will win in the end. In fact, there is a secret that casinos never say: the law of large numbers.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The principle of dice games&lt;/b&gt;&lt;br /&gt;Three dice, bet size, 4-10 is small, 11-17 is big, bet right and win money. And the dice has a kind of round dice, that is, the three dice have the same number of points, and the probability of the round dice is 2.8%. Then the probability of large and small occurrence is 48.6%, respectively. The casino is based on this 2.8% probability. If each gambler bet 100 yuan per game, the casino will win 280 yuan after playing 100 games.&lt;br /&gt;&lt;br /&gt;(0.486+0.028)100100-0.486100100=280&lt;br /&gt;&lt;br /&gt;However, this casino strategy is flawed. If a big player decides to bet tens of billions of dollars on a whim and wins again, the casino will go bankrupt. Therefore, the casino will set a betting limit. If the limit is exceeded, no more bets can be made. In this way, even if the gambler is lucky to win money for a while, in the long run, he will still lose to the probability. In the infinite number of dice games, the gambler will lose 2.8% of the money.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Law of large numbers&lt;/b&gt;&lt;br /&gt;The advantage of the casino owner is only 2% more than that of the gambler. In a single gambling game, the boss may lose money or even suffer continuous losses. However, the casino owner will not be frightened by the loss, because he knows that the &amp;quot;law of large numbers&amp;quot; plays a role in his ability to make money. As long as someone continues to gamble, only a 2% weak advantage is needed to make a long-term stable profit.&lt;br /&gt;&lt;br /&gt;So the casino is not afraid of you winning, but afraid of you not coming. Over the years, you have even heard of bank failures, but when did you hear of casino failures? In the long run, casinos will always be winners. That is to say, gambling for a long time will win.&lt;br /&gt;&lt;br /&gt;Similar examples of winning a long bet are: various lotteries. The lottery pool funds have accumulated more and more since the lottery was listed. Of course, the money comes from the vast number of lottery users. Do you know the probability of 5 million in a double-color ball? The answer is 1 in 17.7 million.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Change of probability&lt;/b&gt;&lt;br /&gt;Suppose there is a coin with the same weight as the front and back, and the probability of throwing the word (back) and the flower (front) is 50%, and each coin toss is independent of the previous result. If you flip the coin 10,000 times in succession, the probability of a flower side is about 50%.&lt;br /&gt;&lt;br /&gt;However, if you only throw 10 times, the probability of a flower side changes, which is not necessarily 50%. Therefore, the casino dealer must ensure that the positive expectation strategy is triggered enough times to be effective. This is also the reason why private equity institutions cannot stop the quantitative trading strategy unless they have special conditions.&lt;br /&gt;&lt;br /&gt;How to use the &amp;quot;law of large numbers&amp;quot; to create a winning strategy in the financial market will be the content of our next series of courses, so look forward to it!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;To sum up&lt;/b&gt;&lt;br /&gt;Above, we have explained to you how to use a scientific approach to deal with trading from the aspects of probability, the reason for trading failure, the correct way of thinking about trading, and the principle of winning at gambling for a long time. I believe that if you have learned something, the change of thinking will be the change of your behavior, and the change of behavior will be the change of your success.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;After-school exercises&lt;/b&gt;&lt;br /&gt;1. Why is trading a game of probability?&lt;br /&gt;2. What are the reasons for trading failure?&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y6_660CIwwU2zfe5yxRVaGDSReR6mrpzY2VTEbtsxgEcQl9VcnBpLmgurRowb5LTWeXtR0LUvdcDVM2r7sZ5Nt6vqEdqCy3CYjnweXMB7U73A" title="https://blog.mathquant.com/2023/02/10/5-6-build-probability-thinking-to-improve-your-trading-pattern.html"&gt;https://blog.mathquant.c...our-trading-pattern.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25699/</id>
    <title type="text">&amp;quot;Get the best deal&amp;quot; analysis of the vulnerability in the exchange</title>
    <published>2024-04-17T03:24:29Z</published>
    <updated>2024-04-17T03:24:29Z</updated>
    <author>
      <name>Trading</name>
      <uri>https://stocksharp.com/users/186421/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#strategy" />
    <category term="#market" />
    <category term="#analysis" />
    <category term="#exchange" />
    <category term="#profit" />
    <category term="#FMZQuant" />
    <category term="#blockchain" />
    <category term="#bug" />
    <content type="html">&lt;b&gt;NO.1 Preface&lt;/b&gt;&lt;br /&gt;In recent years, the digital currency industry based on blockchain technology and cryptography has witnessed explosive growth. As one of the most important links in the digital currency industry chain, the blockchain asset exchange undoubtedly has the priority position. It connects the secondary market of blockchain investment, as well as the project side and ordinary investors.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Background of blockchain asset trading market&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- Operating time of the exchange: the average operating time of the top big exchanges is less than 3 years&lt;br /&gt;- Exchange team: led by small entrepreneurial team&lt;br /&gt;- Number of global trading users: about 10 million to 20 million global trading users&lt;br /&gt;- Global daily transaction fee income: about $25 million&lt;br /&gt;- Growth of the number of global exchanges: from dozens to hundreds&lt;br /&gt;&lt;br /&gt;According to statistics, at present, more than 300 exchanges have been included by non-small platforms, and even thousands of those have not been included. Even so, entrants still enjoy it. Under the background that everyone is involved in the trading, almost every exchange has dozens or even hundreds of trading objects, so in the market with limited stock, small and medium-sized blockchain assets and exchanges will face the situation of lack of flow and a situation of no price and no market.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.2&lt;/b&gt;&lt;br /&gt;&lt;em&gt;Why market maker strategies are just what&amp;#39;s needed&lt;/em&gt;&lt;br /&gt;The emergence of market maker robots has changed this situation. By participating in market making, we can curb excessive speculation in the market due to the asymmetry of information and resources, and maintain the good operation of the trading platform. It also reduces the phenomenon that the so-called dealer secretly manipulates the price in the traditional trading mode to enhance the market attractiveness, improve liquidity and trading volume, meet the buying and selling needs of ordinary investors, and stabilize market confidence.&lt;br /&gt;&lt;br /&gt;Market maker&lt;br /&gt;Buying and selling at asking price&lt;br /&gt;■ Arbitrators&lt;br /&gt;■ Short-term bias&lt;br /&gt;■ Earning spreads&lt;br /&gt;&lt;br /&gt;Market taker &lt;br /&gt;Buyer or seller&lt;br /&gt;■ Traders&lt;br /&gt;■ Investors&lt;br /&gt;■ Producer/consumer&lt;br /&gt;■ Earning or hedging from price fluctuations&lt;br /&gt;&lt;br /&gt;Today, in order to make the new exchange and new currency better connect with ordinary investors and solve many problems faced by them at the initial stage of listing, both small and medium-sized exchanges and blockchain project parties have to rely on market robots.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.3&lt;/b&gt;&lt;br /&gt;&lt;em&gt;Principle of market maker strategy&lt;/em&gt;&lt;br /&gt;Market-making strategy tracks price changes through market making system, and provides two-way quotations for buying and selling constantly. Through a large number of high-frequency buying and selling transactions, accumulate the price difference between each transaction price and the theoretical price gradually, and adjust the price difference dynamically according to the characteristics of the position.&lt;br /&gt;&lt;br /&gt;There are two common market maker strategies in general exchanges:&lt;br /&gt;&lt;br /&gt;Passive market making: Market makers follow the in-depth data and transaction data of the mainstream exchanges through the strategy of tracking, instead of making a big active choice, but passively follow the market. They pursue the maximum degree of close tracking and complete replication, and try to achieve the same K-line data as the mainstream exchanges.&lt;br /&gt;&lt;br /&gt;Free market making: This market making mode does not refer to other trading targets, but makes the market according to its own cost and setting of order. This model is suitable for the environment where the pricing power of relevant currencies is relatively concentrated, such as small blockchain assets or currencies issued by the exchange itself.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.4&lt;/b&gt;&lt;br /&gt;&lt;em&gt;Market maker strategy vulnerability&lt;/em&gt;&lt;br /&gt;Whether it is a passive market making or a free market making, it is necessary to solve not only the price problem of the transaction object, but also the liquidity problem. Therefore, in order to activate the market, it is necessary for the marketers to buy and sell themselves, otherwise it is difficult to form a decent K-line.&lt;br /&gt;&lt;br /&gt;The common method is to sell at a random price near the market and immediately buy at the same price. Or buy before selling according to the random price. Generally, due to the short time interval between trading and buying, the corresponding listing can not be found in the depth data, but the transaction record can be left in the historical data. The K-line is drawn by this market making method.&lt;br /&gt;&lt;br /&gt;**Please pay attention! This is how the vulnerability appears.**&lt;br /&gt;&lt;br /&gt;In order to generate a continuous K-line, the market maker strategy has hidden the vulnerability in the self-buying and self-selling list near the opening of the market. Although the buying order and selling order of the strategy are issued at the same time, the network problem and the matching speed are not ideal, nor can they be ideal, which leads to a certain probability that the order of the marketing strategy will be closed by others.&lt;br /&gt;&lt;br /&gt;Imagine that if there is another high-frequency order strategy in the market, it always deals with the selling orders of the market strategy at a lower price, and deals with the purchase orders of the market strategy at a higher price. As long as the price difference obtained by this high-frequency order strategy can cover the handling charges, it will generate profits. This leads to the strategy of selling low and buying high in the market, think carefully!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.5&lt;/b&gt;&lt;br /&gt;&lt;em&gt;Practical demonstration&lt;/em&gt;&lt;br /&gt;After observation, there is a market making phenomenon in **the ETHUSDT trading pair of a certain exchange**, and the reference object may be the ETHUSDT data of Binance. By observing the data of its market order book, it is found that there is a self-closing order, and the trading direction is random. The chart below shows the K-line generated by the market making strategy on that day.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150331
" title="https://stocksharp.com/file/150331
"&gt;https://stocksharp.com/file/150331
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Usually, the high-frequency order strategy is not randomly priced at the opening of the market, but randomly changes with reference to the last transaction price of the market strategy. In fact, it is difficult for the transaction price to reach the low and high market prices, and the success rate of obtaining market making strategy orders is limited, so there is almost no profit.&lt;br /&gt;&lt;br /&gt;They even have to bear the risk of unilateral positions. This seems to be impeccable, but if we take advantage of the bug that market making orders must be placed in the market, we can easily crack the market strategy of the exchange and make great profits.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.6&lt;/b&gt;&lt;br /&gt;&lt;b&gt;The specific steps are as follows:&lt;/b&gt;&lt;br /&gt;When expecting a low price deal, add a certain price to the buy one price to pend a selling order. When the buy price is 200, pend a selling order of 200.1, then keep pending a buying order of 200.09, and withdraw immediately. When the transaction is completed, reverse the operation immediately and sell the traded currency at a high price, thus completing a loop.&lt;br /&gt;&lt;br /&gt;Although such a success rate is not very high, through a large number of frequent pending order and cancellation transactions, this opportunity will be greatly increased and the profit will still be considerable.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150330
" title="https://stocksharp.com/file/150330
"&gt;https://stocksharp.com/file/150330
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As shown in the chart above, **a high-frequency order strategy was written through the FMZ Quant Trading Platform (FMZ) and run in the real market with almost no withdraw**. In only one night, the profit of 1,000USDT was transferred to 4,000USDT.&lt;br /&gt;&lt;br /&gt;This is a gentle order. If you use multiple accounts, multiple contracts, and multiple threads, you will increase profits. After the high-frequency order strategy takes advantage of this vulnerability, it steals a huge amount of money and leaves behind a dreadful of the K-line, as shown in the following chart:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150332
" title="https://stocksharp.com/file/150332
"&gt;https://stocksharp.com/file/150332
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.7&lt;/b&gt;&lt;br /&gt;The source code of the order strategy based on the vulnerability of the exchange market&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150333
" title="https://stocksharp.com/file/150333
"&gt;https://stocksharp.com/file/150333
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The above strategy source code is based on the FMZ Quant Trading Platform (www.fmz.cn)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.8&lt;/b&gt;&lt;br /&gt;&lt;em&gt;Prevention methods&lt;/em&gt;&lt;br /&gt;For this market making strategy, it is easy to solve the problem after knowing the principle. For example, when the transaction price of the market making strategy is at a low level, only the buy order is placed first and then the sell order, and vice versa, so that others will not buy it at a low price and sell it at a high price. Or put all transactions and pending orders in the scope that can be hedged in other exchanges.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Words to follow&lt;/b&gt;&lt;br /&gt;**Although the exchange is at the top of the entire blockchain industry**, it is like a giant outside, revealing more attack areas and exploitable vulnerabilities.&lt;br /&gt;&lt;br /&gt;Objectively speaking, the irrationality that can be deduced from the order book may have more hidden bugs. For example, by taking advantage of the obvious vulnerabilities in the strategies of exchange market makers, attackers can skillfully design various covert attack strategies, and they can also do it unknowingly.&lt;br /&gt;&lt;br /&gt;**Today, digital currency has become a new target for investment, and exchanges have become an arena for many hackers**. The hackers hiding in the dark are like hungry wolves, waiting for the opportunity to move, staring at the flaws of the exchange, and preparing for a fatal attack. The blockchain centralized exchange can only strengthen its own defense deployment, so that customers can have worry-free transactions.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y65ZXs8chpdiMjV875_7hv8jqDmL5u993bwm5PXXFDvfWpvZ2kEgDkkmuSM5u9POOmheVbsBFFf0gtVOD3LzwoCZPag9xRnJkxk7vtfH6Nr9q" title="https://blog.mathquant.com/2023/02/10/get-the-best-deal-analysis-of-the-vulnerability-in-the-exchange.html"&gt;https://blog.mathquant.c...ity-in-the-exchange.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25698/</id>
    <title type="text">Can we make quantitative trading without code? Let&amp;apos;s find out...</title>
    <published>2024-04-17T02:14:57Z</published>
    <updated>2024-04-17T02:14:57Z</updated>
    <author>
      <name>Trading</name>
      <uri>https://stocksharp.com/users/186421/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#strategy" />
    <category term="#code" />
    <category term="#market" />
    <category term="#platform" />
    <category term="#FMZQuant" />
    <category term="#programming" />
    <category term="#blockly" />
    <category term="#visualization" />
    <content type="html">&lt;b&gt;NO.1&lt;/b&gt;&lt;br /&gt;On Wall Street, quantitative trading has become the leading role of market trading. Many of the world&amp;#39;s top investment banks have banned manual directional speculative trading. The development of quantitative trading in China is also very rapid. Institutions are using it, and future tycoons are also using it. There are more and more people participating in quantitative trading.&lt;br /&gt;&lt;br /&gt;But there are also many manual traders who are interested in quantitative trading. At the beginning, they were full of confidence. After reading the long and complex code, they often hesitated or stopped. In order to popularize the public, reduce the threshold of quantitative trading programming, and improve the efficiency of writing greatly, FMZ has developed a visual quantitative trading platform.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.2&lt;/b&gt;&lt;br /&gt;In traditional programming, you should be familiar with the basic grammar, data operation, data structure, logic control... of programming language. Let&amp;#39;s write a program that outputs &amp;quot;hello, world&amp;quot; in Java to experience traditional programming, as follows:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150316
" title="https://stocksharp.com/file/150316
"&gt;https://stocksharp.com/file/150316
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It took 5 lines of code just to output a string program. I believe that most beginners only know the &amp;quot;hello, world&amp;quot; in parentheses, and nothing else. Therefore, it is a better choice to start with visual programming.&lt;br /&gt;&lt;br /&gt;Visual programming has a long history and is not new. The &amp;quot;what you see is what you get&amp;quot; programming idea, carrying various control modules, can build code logic and complete trading strategy design just by dragging, and the process is very like building blocks.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150317
" title="https://stocksharp.com/file/150317
"&gt;https://stocksharp.com/file/150317
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As shown in the chart above, the same program needs only one line of code in blockly visual programming, which reduces the programming threshold greatly, especially for those traders who do not understand programming at all. This is a very good operating experience. The FMZ Quant visual programming is also realized through the blocky visualization tool released by Google. In design, it is the same as the Scratch launched by Massachusetts Institute of Technology, so there is really - no barrier.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150319
" title="https://stocksharp.com/file/150319
"&gt;https://stocksharp.com/file/150319
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The FMZ Quant visual programming, with hundreds of commonly used trading modules built in, will have more trading modules added in the future to support traders&amp;#39; new ideas and new applications, which will be jointly developed and maintained by developers. Although the grammar is simple, it does have performance. It can almost meet most quantitative trading strategies. In terms of function and speed, it is not inferior to conventional programming languages such as Python and JavaScript. In the future, financial applications with complex logic will be supported.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.3&lt;/b&gt;&lt;br /&gt;**How to use**&lt;br /&gt;&lt;br /&gt;**Step 1**: Register and sign in the FMZ Quant (**FMZ**) website at: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAC8JkNV3nsAiF_sZq5srY9__oQAbvK03HYua0an4O9H4w" title="http://www.fmz.com"&gt;www.fmz.com&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150315
" title="https://stocksharp.com/file/150315
"&gt;https://stocksharp.com/file/150315
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;**Step 2**: Go to Dashboard&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150318
" title="https://stocksharp.com/file/150318
"&gt;https://stocksharp.com/file/150318
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;**Step 3**: Click add strategy&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150320
" title="https://stocksharp.com/file/150320
"&gt;https://stocksharp.com/file/150320
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;**Step 4**: Select Blockly and Template Include&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150321
" title="https://stocksharp.com/file/150321
"&gt;https://stocksharp.com/file/150321
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;**Finally**, we are in the visual programming interface, as follows:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150319
" title="https://stocksharp.com/file/150319
"&gt;https://stocksharp.com/file/150319
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.4&lt;/b&gt;&lt;br /&gt;Try to write a program that outputs &amp;quot;hello, world&amp;quot; using the FMZ Quant blockly editor&lt;br /&gt;&lt;br /&gt;**Step 1: Select Log module**&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150323
" title="https://stocksharp.com/file/150323
"&gt;https://stocksharp.com/file/150323
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;**Step 2: Select Text module**&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150326
" title="https://stocksharp.com/file/150326
"&gt;https://stocksharp.com/file/150326
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;**Step 3: Backtest settings**&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150324
" title="https://stocksharp.com/file/150324
"&gt;https://stocksharp.com/file/150324
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;**Step 4: Backtest result**&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150325
" title="https://stocksharp.com/file/150325
"&gt;https://stocksharp.com/file/150325
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.5&lt;/b&gt;&lt;br /&gt;**A complete dynamic balancing strategy for digital currencies**&lt;br /&gt;&lt;br /&gt;**Strategy logic**&lt;br /&gt;&lt;br /&gt;- Condition for buying: If the market value of the current position minus the current available balance is less than 5% of the negative current available balance, open a position to buy.&lt;br /&gt;&lt;br /&gt;- Condition for selling: If the market value of the current position minus the current available balance is more than 5% of the negative current available balance, close a position to sell.&lt;br /&gt;&lt;br /&gt;**Prerequisites and requirements**&lt;br /&gt;&lt;br /&gt;- Current market&lt;br /&gt;&lt;br /&gt;- Current assets&lt;br /&gt;&lt;br /&gt;- Total market value of currency&lt;br /&gt;&lt;br /&gt;- Asset difference&lt;br /&gt;&lt;br /&gt;**Blockly strategy-writing Step 1**&lt;br /&gt;&lt;br /&gt;We calculate the four prerequisites and prerequisites of the trading strategy and assign values to each variable. With visual programming, the code block is like this, as shown below:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150322
" title="https://stocksharp.com/file/150322
"&gt;https://stocksharp.com/file/150322
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It should be noted that the total market value of the currency is the total market value of the current currency holdings. The calculation method is to multiply the current total currency holdings by the current latest price. The asset difference is the total market value of the currency minus the current available balance.&lt;br /&gt;&lt;br /&gt;**Blockly strategy-writing Step 2**&lt;br /&gt;&lt;br /&gt;After the assignment of prerequisites and prerequisites is completed, the trading logic needs to be written. This is not as complicated as expected. It is nothing more than to express the above strategy logic in the form of code blocks. That is, if the asset difference is less than 5% of the negative available balance, buy it, and if the asset difference is greater than 5% of the available balance, sell it. As shown below:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150328
" title="https://stocksharp.com/file/150328
"&gt;https://stocksharp.com/file/150328
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The whole strategy seems to have finished, but you should know that the program is executed from top to bottom, and then it stops. However, our trading strategy is not to execute the trading conditions once, but to execute them in a loop repeatedly. In other words, the program needs to check whether the strategic conditions have been reached constantly. If so, it will execute the trading, otherwise it will continue to check. At this time, another loop statement is needed, as shown in the following figure:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150327
" title="https://stocksharp.com/file/150327
"&gt;https://stocksharp.com/file/150327
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There is no essential difference between the visualization strategy and the strategy written in other programming languages. It also supports the historical data test with multiple periods and accuracies. Of course, it also supports the real market trading of domestic and foreign commodity futures and digital currency. The following is the backtest information of the strategy:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150329
" title="https://stocksharp.com/file/150329
"&gt;https://stocksharp.com/file/150329
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So far, a complete trading strategy has finished. In order to take care of the lazy guys, this strategy has been shared in the strategy square and it can be copied for study directly.&lt;br /&gt;&lt;br /&gt;Strategy link address:&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAADHZKb-RfbDOdB_w3dJgQKtn2auqCf9hSdLnVG5SPqdEmJs4KZ5n5eXcXZ3hXdDpoo" title="https://www.fmz.com/strategy/121404
"&gt;https://www.fmz.com/strategy/121404
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NO.6&lt;/b&gt;&lt;br /&gt;The law of ten thousand hours always exists, but for traders with zero basis, it is impossible to spend ten thousand hours practicing again. So you must have a ladder, and for traders with zero programming foundation, the FMZ Quant visual programming is a ladder to get started quickly.&lt;br /&gt;&lt;br /&gt;With visual programming, you don&amp;#39;t need to remember the grammar and method name, just simply browse the function module to find what you want. The original intention of the FMZ Quant is also to help more quantitative beginners reduce the entry threshold and increase their interest in quantification. Everyone can become a quantitative trader!&lt;br /&gt;&lt;br /&gt;However, in other words, visual programming is no problem as a step to quantitative entry, but it also has its own limitations, such as the inability to develop overly complex and sophisticated trading strategies. But this does not affect you to take the first step of quantitative trading!&lt;br /&gt;&lt;br /&gt;Finally, I wish all friends who want to do quantitative trading, regardless of whether they are based on zero, can achieve their learning goals through action. Thank you for reading!&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y6-UQKeUqBZ6P43vdcFhaevU5uV-oEl2B1y5V0JfTQq_hVFc8rOCbAj2HCJD6ScZOhW6-_rWIrVvyj3U08hU_b7PU-8kYR-iuBaO3XwWZdD2V" title="https://blog.mathquant.com/2023/02/13/can-we-make-quantitative-trading-without-code-lets-find-out.html"&gt;https://blog.mathquant.c...-code-lets-find-out.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25697/</id>
    <title type="text">Concurrent Strategy Execution with JavaScript Multithreading Support</title>
    <published>2024-04-17T01:07:43Z</published>
    <updated>2024-04-17T01:07:43Z</updated>
    <author>
      <name>Trading</name>
      <uri>https://stocksharp.com/users/186421/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#strategy" />
    <category term="#code" />
    <category term="#exchange" />
    <category term="#javascript" />
    <category term="#FMZQuant" />
    <category term="#function" />
    <category term="#thread" />
    <category term="#system" />
    <category term="#loop" />
    <content type="html">When developing strategies on FMZ using the JavaScript language, since the strategy architecture is polled. If there is a concurrent design scenario, the ```exchange.Go``` function is used to make concurrent calls to some interfaces, so as to meet the requirements of some concurrent scenarios. But if you want to create a single thread to perform a series of operations, it is impossible. For example, like the Python language, use the ```threading``` library to do some concurrent design.&lt;br /&gt;&lt;br /&gt;Based on this requirement, the FMZ platform has upgraded the bottom layer of the system. True multithreading support has also been added to the JavaScript language. Detailed features include:&lt;br /&gt;&lt;br /&gt;- Create threads to execute custom functions concurrently.&lt;br /&gt;- Inter-thread communication.&lt;br /&gt;- Variables stored between shared threads.&lt;br /&gt;- Wait for the thread to finish executing to reclaim resources and return the execution result.&lt;br /&gt;- Forcibly end the thread and reclaim resources.&lt;br /&gt;- Get the current thread ID in the concurrent thread execution function.&lt;br /&gt;&lt;br /&gt;Next, I will take you to understand each function one by one.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Create threads to execute custom functions concurrently&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;The ```__Thread``` function can create a thread and execute a function concurrently. For example, you need to create a concurrent function ```func1```, what does the ```func1``` function do? We can let it accumulate from 0 to 9. In order to see the gradual accumulation process, we use the for loop in the func1 function to pause each time (the Sleep function is used to sleep for a certain number of milliseconds) for a certain period of time.&lt;br /&gt;```&lt;br /&gt;function func1(sleepMilliseconds) {&lt;br /&gt;    var sum = 0 &lt;br /&gt;    for (var i = 0 ; i &amp;lt; 10 ; i++) {&lt;br /&gt;        sum += i &lt;br /&gt;        Sleep(sleepMilliseconds)&lt;br /&gt;        Log(&amp;quot;sum:&amp;quot;, sum)&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return sum&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function main() {&lt;br /&gt;    // Use the __Thread function to create a thread concurrently, and the parameter 200 is the parameter of the func1 function,&lt;br /&gt;    // If the func1 function has multiple parameters, here we pass the corresponding parameters.&lt;br /&gt;    var thread1Id = __Thread(func1, 200)&lt;br /&gt;    &lt;br /&gt;    // Here we need to wait for the execution result of the thread whose thread Id is thread1Id, otherwise all threads will be released directly after the main function is executed.&lt;br /&gt;    var ret = __threadJoin(thread1Id)&lt;br /&gt;    Log(&amp;quot;ret:&amp;quot;, ret)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;In practical applications, we can make http requests concurrently like this:&lt;br /&gt;```&lt;br /&gt;function main() {&lt;br /&gt;    let threads = [&lt;br /&gt;        &amp;quot;https://www.baidu.com&amp;quot;,&lt;br /&gt;        &amp;quot;https://www.163.com&amp;quot;&lt;br /&gt;    ].map(function(url) {&lt;br /&gt;        return __Thread(function(url) {&lt;br /&gt;            Log(&amp;quot;GET&amp;quot;, url)&lt;br /&gt;            return HttpQuery(url)&lt;br /&gt;        }, url)&lt;br /&gt;    })&lt;br /&gt;    threads.forEach(function(tid) {&lt;br /&gt;        Log(__threadJoin(tid))&lt;br /&gt;    })&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Wait for the end of thread execution to reclaim resources and return the execution result&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;In the above example, we used the ```__threadJoin``` function in the main function finally to wait for the concurrent threads to finish executing. The variable ```ret``` receives the return value of the ```__threadJoin``` function, and we print the return value, we can observe the specific results of the concurrent thread execution.&lt;br /&gt;```&lt;br /&gt;// id: thread ID, terminated: whether it was forced to stop, elapsed: time-consuming (nanoseconds), ret: the return value of the thread execution function&lt;br /&gt;ret: {&amp;quot;id&amp;quot;:1,&amp;quot;terminated&amp;quot;:false,&amp;quot;elapsed&amp;quot;:2004884301,&amp;quot;ret&amp;quot;:45}&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;End the thread forcibly and reclaim resources&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;```&lt;br /&gt;function func1(sleepMilliseconds) {&lt;br /&gt;    var sum = 0 &lt;br /&gt;    for (var i = 0 ; i &amp;lt; 10 ; i++) {&lt;br /&gt;        sum += i &lt;br /&gt;        Sleep(sleepMilliseconds)&lt;br /&gt;        Log(&amp;quot;sum:&amp;quot;, sum)&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return sum&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function main() {&lt;br /&gt;    var thread1Id = __Thread(func1, 200)&lt;br /&gt;    Sleep(1000)&lt;br /&gt;    retThreadTerminate = __threadTerminate(thread1Id)&lt;br /&gt;    Log(retThreadTerminate)   // true&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;We still use the example just now, after creating a thread, you can forcibly terminate the execution of the thread after waiting for 1 second.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Inter-thread communication&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Inter-thread communication mainly uses the ```__threadPostMessage``` function and the ```__threadPeekMessage``` function. Let&amp;#39;s look at the following simple example:&lt;br /&gt;```&lt;br /&gt;function func1() {&lt;br /&gt;    var id = __threadId()&lt;br /&gt;    while (true) {&lt;br /&gt;        var postMsg = &amp;quot;Message from thread function func1&amp;quot; with &amp;quot;from id:&amp;quot; + id + &lt;br /&gt;        __threadPostMessage(0, postMsg)              // Send a message to the main thread&lt;br /&gt;        var peekMsg = __threadPeekMessage()         // Receive messages from other threads&lt;br /&gt;        Log(peekMsg)&lt;br /&gt;        Sleep(5000)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function main() {&lt;br /&gt;    var threadId = __Thread(func1)&lt;br /&gt;    &lt;br /&gt;    while (true) {&lt;br /&gt;        var postMsg = &amp;quot;Messages from the main function of the main thread&amp;quot;&lt;br /&gt;        __threadPostMessage(threadId, postMsg)&lt;br /&gt;        var peekMsg = __threadPeekMessage(threadId)&lt;br /&gt;        Log(peekMsg, &amp;quot;#FF0000&amp;quot;)                     // #FF0000 , Set the log to red for distinction&lt;br /&gt;        Sleep(5000)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;The ```__threadPostMessage``` function is used to send a message to a thread. The first parameter is the ID of the specific thread to send to, and the second parameter is the message to be sent, which can be a string, a value, an array, or a JSON object and so on. Messages can be sent to the main thread in concurrent thread functions, and the ID of the main thread is defined as 0.&lt;br /&gt;&lt;br /&gt;The ```__threadPeekMessage``` function is used to monitor the message sent by a certain thread. It can set the timeout time (in milliseconds), or it can be set to 0, which means blocking, and it will not return until there is a message.&lt;br /&gt;&lt;br /&gt;Of course, except for concurrent threads communicating with the main thread. Concurrent threads can also communicate with each other directly.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Get the current thread ID in the concurrent thread execution function&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;In the above example, the function ```var id = __threadId()，__threadId()``` is used to get the ID of the current thread.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;Variables stored between shared threads&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;In addition to communication between threads, shared variables can also be used for interaction.&lt;br /&gt;```&lt;br /&gt;function testFunc() {&lt;br /&gt;    __threadSetData(0, &amp;quot;testFunc&amp;quot;, 100)   // Stored in the current thread environment, key-value pair testFunc : 100&lt;br /&gt;    Log(&amp;quot;testFunc execution completed&amp;quot;)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function main() {&lt;br /&gt;    // threadId is 1, the created thread with threadId 1 will be executed first, as long as the thread resources are not reclaimed, the variables stored locally in the thread will be valid&lt;br /&gt;    var testThread = __Thread(testFunc)&lt;br /&gt;    &lt;br /&gt;    Sleep(1000)&lt;br /&gt;&lt;br /&gt;    // export in main, get testFunc: 100&lt;br /&gt;    Log(&amp;quot;in main, get testFunc:&amp;quot;, __threadGetData(testThread, &amp;quot;testFunc&amp;quot;))   // Take out the value whose key name is testFunc&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;The above is a simple demonstration of all functions.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y68da49bEAcF-zo9hFF6lkEJWdhFjJ4ccYcKl7IRkuOTs7C11E9GF8lT0470P8OtPdUL50g58AtwBpbuqpdtScjTEjOoX48E9Ar9S42SzA_feWM53nCw3Y7DAaH1z7JIDPUs_9FITfSaKbJPjK4jQxlE9yZdrpaK-hoLRg4N0I2xng9_9hdNqJg78qN60xQKmTRujvqLSzdfnG6IEENwJVQ0" title="https://blog.mathquant.com/2023/03/07/let-the-strategy-program-be-executed-concurrently-and-add-multi-thread-support-at-the-bottom-of-the-system-to-the-javascript-strategy.html"&gt;https://blog.mathquant.c...javascript-strategy.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25695/</id>
    <title type="text">How to Solve the World Pi Day OKX Private Key Puzzle Award (with complete code)</title>
    <published>2024-04-16T09:22:15Z</published>
    <updated>2024-04-16T09:22:15Z</updated>
    <author>
      <name>FMZ</name>
      <uri>https://stocksharp.com/users/186354/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#code" />
    <category term="#OKX" />
    <category term="#python" />
    <category term="#FMZQuant" />
    <category term="#address" />
    <category term="#wallet" />
    <category term="#debug" />
    <category term="#programmer" />
    <content type="html">I saw some Tycoons in the group saying that OKX was holding a World Pi Day Mystery Event, with the theme of &amp;quot;Exploration, Never Ending&amp;quot;.&lt;br /&gt;&lt;br /&gt;As a veteran programmer, when I saw the news, I smiled and opened my MacBook Pro, and without further ado, let&amp;#39;s get started!&lt;br /&gt;&lt;br /&gt;&amp;gt; Analysis&lt;br /&gt;&lt;br /&gt;Officially, there are 61 bits of key in the picture and the part of the circumference overlap, as we all know, the length of private key is 32 byte, converted to hex is 64 bits plus 0x prefix, a total of 66 bits, there are already 61 bits, for the first look, the &amp;quot;0X&amp;quot; at the first line in the chart is obviously not Pi, it is the start of the private key prefix, then there are about 5 bits (0123456789ABCDEF). The characters are arranged randomly, so there&amp;#39;s nothing wrong with running them directly, so let&amp;#39;s get started~&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s use a Mac tool to sharpen the color simply:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150303
" title="https://stocksharp.com/file/150303
"&gt;https://stocksharp.com/file/150303
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In this way, the Mac can recognize the characters on the picture automatically. Let&amp;#39;s copy them directly:&lt;br /&gt;```&lt;br /&gt;3.141592653589793230X1D64338&lt;br /&gt;А694502884197169399375105820&lt;br /&gt;974925E123078164062862089986&lt;br /&gt;28033DB034211706409914808651&lt;br /&gt;32823066470ED424609550582231&lt;br /&gt;8B3&lt;br /&gt;81284&lt;br /&gt;• Exploration, &lt;br /&gt;038&lt;br /&gt;Never Ending&lt;br /&gt;027&lt;br /&gt;493&lt;br /&gt;05%&lt;br /&gt;0128&lt;br /&gt;4756482337867831731712019091&lt;br /&gt;47D9E56692346034861045432664&lt;br /&gt;8213393607743749141273724587&lt;br /&gt;006606315588174881BEEA209628&lt;br /&gt;2925409192744436789259036001&lt;br /&gt;```&lt;br /&gt;It cannot be used directly. Let&amp;#39;s correct it manually. The unconfirmed ones covered by the picture are marked with *. Not sure. Let&amp;#39;s talk about it later.&lt;br /&gt;The others blocked by the figure can be judged by observing the stroke shape of other fonts. At this time, we use Python to calculate the difference between the two, and use &amp;#39;_&amp;#39; for the same ones and only showing the different ones.&lt;br /&gt;```&lt;br /&gt;img = &amp;#39;&amp;#39;&amp;#39;&lt;br /&gt;3.141592653589793230X1D64338&lt;br /&gt;A694502884197169399375105820&lt;br /&gt;974925E123078164062862089986&lt;br /&gt;28033DB034211706409914808651&lt;br /&gt;32823066470ED424609550582231&lt;br /&gt;8B32594081284811174502841027&lt;br /&gt;0193**2*D2299964462294895493&lt;br /&gt;0381960EFC8103F9365933446128&lt;br /&gt;4756482337867831731712019091&lt;br /&gt;47D9E56692346034861045432664&lt;br /&gt;82133936077A3749141273724587&lt;br /&gt;006606315588174881BEEA209628&lt;br /&gt;2925409192744436789259036001&lt;br /&gt;&amp;#39;&amp;#39;&amp;#39;&lt;br /&gt;# True Pi&lt;br /&gt;real=&amp;#39;&amp;#39;&amp;#39;&lt;br /&gt;3.14159265358979323846264338&lt;br /&gt;3279502884197169399375105820&lt;br /&gt;9749445923078164062862089986&lt;br /&gt;2803482534211706798214808651&lt;br /&gt;3282306647093844609550582231&lt;br /&gt;7253594081284811174502841027&lt;br /&gt;0193852110555964462294895493&lt;br /&gt;0381964428810975665933446128&lt;br /&gt;4756482337867831652712019091&lt;br /&gt;4564856692346034861045432664&lt;br /&gt;8213393607260249141273724587&lt;br /&gt;0066063155881748815209209628&lt;br /&gt;2925409171536436789259036001&lt;br /&gt;&amp;#39;&amp;#39;&amp;#39;&lt;br /&gt;&lt;br /&gt;items = img.strip().split(&amp;#39;\n&amp;#39;)&lt;br /&gt;diffStr = &amp;#39;&amp;#39;&lt;br /&gt;for pos, line in enumerate(real.strip().split(&amp;#39;\n&amp;#39;)):&lt;br /&gt;    for i, c in enumerate(line):&lt;br /&gt;        imgLine = list(items[pos])&lt;br /&gt;        if line[i] == imgLine[i]:&lt;br /&gt;            imgLine[i] = &amp;#39;_&amp;#39;&lt;br /&gt;        else:&lt;br /&gt;            diffStr += imgLine[i]&lt;br /&gt;        items[pos] = &amp;#39;&amp;#39;.join(imgLine)&lt;br /&gt;print(&amp;#39;\n&amp;#39;.join(items))&lt;br /&gt;print(diffStr, &amp;#39;Len:&amp;#39;, len(diffStr))&lt;br /&gt;```&lt;br /&gt;The implementation results are as follows:&lt;br /&gt;```&lt;br /&gt;___________________0X1D_____&lt;br /&gt;A694________________________&lt;br /&gt;____25E1____________________&lt;br /&gt;____3DB0________4099________&lt;br /&gt;___________ED42_____________&lt;br /&gt;8B32________________________&lt;br /&gt;____**_*D2299_______________&lt;br /&gt;______0EFC___3F93___________&lt;br /&gt;________________731_________&lt;br /&gt;_7D9E_______________________&lt;br /&gt;__________7A37______________&lt;br /&gt;__________________BEEA______&lt;br /&gt;________92744_______________&lt;br /&gt;0X1DA69425E13DB04099ED428B32***D22990EFC3F937317D9E7A37BEEA92744 Len: 64&lt;br /&gt;```&lt;br /&gt;There are three more, and there are just three uncertain ones. Try to remove them, because the other 61 bits are all right after exclusion, leaving only the most definite difference. Finally, the prefix is as follows:&lt;br /&gt;```&lt;br /&gt;0X1DA69425E13DB04099ED428B32D22990EFC3F937317D9E7A37BEEA92744&lt;br /&gt;```&lt;br /&gt;Next, we shall use Python and use force to crawl the balance on the OK chain. We can compare which private key has the balance. In fact, we can also select the public key with 314 USDT transfer first, which is faster. Seeing information on the official website said that we can check the balance directly if there is gas, the code is a little messy.&lt;br /&gt;```&lt;br /&gt;import sys&lt;br /&gt;import web3,time,logging&lt;br /&gt;from eth_account import Account&lt;br /&gt;from web3 import Web3&lt;br /&gt;logging.basicConfig(level=logging.INFO, format=&amp;#39;%(asctime)s %(message)s&amp;#39;)&lt;br /&gt;w3 = Web3(Web3.HTTPProvider(&amp;quot;https://exchainrpc.okex.org&amp;quot;))&lt;br /&gt;logging.info(w3.clientVersion)&lt;br /&gt;found = None&lt;br /&gt;&lt;br /&gt;def get_balance_gas(key):&lt;br /&gt;    global found&lt;br /&gt;    _counter += 1&lt;br /&gt;    address = Account.from_key(key).address&lt;br /&gt;    logging.info(&amp;#39;fetch address %s %s&amp;#39; % (found, address))&lt;br /&gt;    while True:&lt;br /&gt;        try:&lt;br /&gt;            balance = w3.eth.get_balance(address)&lt;br /&gt;            break&lt;br /&gt;        except:&lt;br /&gt;            logging.warning(traceback.format_exc())&lt;br /&gt;            time.sleep(1)&lt;br /&gt;            continue&lt;br /&gt;    if balance != 0:&lt;br /&gt;        found = key&lt;br /&gt;        raise BaseException(&amp;#39;Found balance: %s %s&amp;#39; % (address, balance))&lt;br /&gt;    return balance&lt;br /&gt;&lt;br /&gt;from concurrent.futures import ThreadPoolExecutor&lt;br /&gt;executor = ThreadPoolExecutor(max_workers=50)&lt;br /&gt;keys = []&lt;br /&gt;prefix = &amp;#39;1DA69425E13DB04099ED428B32D22990EFC3F937317D9E7A37BEEA92744&amp;#39;&lt;br /&gt;# It doesn&amp;#39;t matter how to optimize the algorithm. Run the secret key against the clock.&lt;br /&gt;ch = &amp;#39;0123456789ABCDEF&amp;#39;&lt;br /&gt;for a in range(0, 16):&lt;br /&gt;    for b in range(0, 16):&lt;br /&gt;        for c in range(0, 16):&lt;br /&gt;            for d in range(0, 16):&lt;br /&gt;                for e in range(0, 16):&lt;br /&gt;                    keys.append(&amp;quot;0x&amp;quot;+prefix+ch[a]+ch[b]+ch[c]+ch[d]+ch[e])&lt;br /&gt;print(&amp;#39;all keys:&amp;#39;, len(keys))&lt;br /&gt;tasks = [None for t in keys]&lt;br /&gt;for idx, key in enumerate(keys):&lt;br /&gt;    tasks[idx] = executor.submit(get_balance_gas, key)&lt;br /&gt;for t in tasks:&lt;br /&gt;    t.result()&lt;br /&gt;    &lt;br /&gt;```&lt;br /&gt;We can see that it takes 1048576 iterations, but it&amp;#39;s much faster with multi-threading, running it on one of my servers.&lt;br /&gt;```&lt;br /&gt;2023-03-15 00:20:19,491 exchain-v1.6.8.5&lt;br /&gt;all keys: 1048576&lt;br /&gt;2023-03-15 00:20:20,372 fetch address None 0xc20C41f06F2428a0FD84ef03Ec6960992F5f8016&lt;br /&gt;2023-03-15 00:20:20,473 fetch address None 0xcFa87ee54bc1c14c09a3AB3f41640bBab5C5480a&lt;br /&gt;2023-03-15 00:20:20,483 fetch address None 0x126E922652f8B276F231D0eCA94d98685a26a45D&lt;br /&gt;The following is omitted...&lt;br /&gt;```&lt;br /&gt;Anxious waiting~~~, bad news came, and there was no result before the strategy exited. All of them were displayed as None.&lt;br /&gt;&lt;br /&gt;&amp;gt; The path winds along mountain ridges&lt;br /&gt;&lt;br /&gt;I don&amp;#39;t think so, I can&amp;#39;t figure it out, I started to look at the discussion on twitter, and I found that everyone and I arrived at the same steps, but the strange thing is that no one has said that the decryption is successful, and the official has not announced the correct first 61 bits, then a strange reply caught my attention, because there is a difference ```D2299``` in the middle, I am very sure, but he looks terribly confident.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150300
" title="https://stocksharp.com/file/150300
"&gt;https://stocksharp.com/file/150300
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;However, he posted a 61-bit D2290. He also said that he had been checked carefully. It doesn&amp;#39;t matter. Take a chance. Anyway, it&amp;#39;s a waste of electricity.&lt;br /&gt;With the attitude of trying, I found a few other people who said that they had found 61-bit. They were all very confident.&lt;br /&gt;The prefixes found in the comments section are collected, with the code just traversed, the basic code has not changed, and it will not be pasted repeatedly.&lt;br /&gt;```&lt;br /&gt;prefixs =[&lt;br /&gt;&amp;#39;1DA69425E13DB04099ED428B3202290EFC3F9317317D9E7A37BEEA92744&amp;#39;,&lt;br /&gt;&amp;#39;1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744&amp;#39;,&lt;br /&gt;&amp;#39;1DA69425E13DB04099ED428B320D2290EFC3F937317D9E7A37BEEA92744&amp;#39;,&lt;br /&gt;&amp;#39;1DA694255E3DB040990ED428B3208890EFC3F937317D9E7A37BEEA92744&amp;#39;,&lt;br /&gt;&amp;#39;1DA69425E13DB04099ED428B3202299EFC3F9317317D9E7A37BEEA92744&amp;#39;,&lt;br /&gt;&amp;#39;1DA69425E13DB01099ED428B3202290EFC3F9317317D9E7A37BEEA92744&amp;#39;,&lt;br /&gt;&amp;#39;1DA69425E13DB04099ED428B32D2290EFC3F9317317D9E7A37BEEA92744&amp;#39;,&lt;br /&gt;&amp;#39;1DA69425E13DB04099ED428B32D22990EFC3F937317D9E7A37BEEA92744&amp;#39;,&lt;br /&gt;]&lt;br /&gt;```&lt;br /&gt;In fact, there are more new messages later, one brother&amp;#39;s PI value is different from mine, it&amp;#39;s amazing!&lt;br /&gt;Let&amp;#39;s run with these first, I can&amp;#39;t believe my eyes, but it came out, it means that one of the prefixes above is correct, which is very unscientific, the private key is:&lt;br /&gt;```&lt;br /&gt;1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744C8155&lt;br /&gt;```&lt;br /&gt;Here is D229, but the picture is clearly D2299, and 731 is followed by 7, here is two, but actually, this is the correct 61 bits, how he calculated it himself is unknown, incredibly curious, but I do not doubt my own operation, I saw one of the comments said that the official customer service said Pi has another version, it was me who were ignorant, with what I have learned and the current human understanding of the universe understanding, the circumference of this irrational number can represent the infinity of the universe, its fractional part never repeats or terminates, you can interpret it as the UUID of the universe you are in, if there are other versions, probably from parallel worlds.&lt;br /&gt;&lt;br /&gt;&amp;gt; Web3 currency conversion code&lt;br /&gt;&lt;br /&gt;Finally, it&amp;#39;s the code to transfer the bonus away, for this time, I use the FMZ platform Web3 directly, set the chain address to OKC, the private key added to the exchange at random, and then two lines will be done, execute it in the debug tool mode directly.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150302
" title="https://stocksharp.com/file/150302
"&gt;https://stocksharp.com/file/150302
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&amp;gt; Proof&lt;br /&gt;&lt;br /&gt;Address of the decrypted public key&lt;br /&gt;```&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; from eth_account import Account&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; Account.from_key(&amp;#39;0x1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744C8155&amp;#39;).address&lt;br /&gt;&amp;#39;0x0bd08825e05e540C9508961a32E58D14da47275A&amp;#39;&lt;br /&gt;```&lt;br /&gt;Check out the link: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAX6jgKcm1O1gelyLxYvVdIbt9cn3p71T5OwEE4vsaq2PnkVSpqpu-oQhh8CumLz_gqis0OY5p8TC18yoMVoV04IYV7292ckz8vvWeoOH5AxVdgH8L1PV3WluBEmbWiD9o" title="https://www.okx.com/cn/explorer/okc/address/0x0bd08825e05e540c9508961a32e58d14da47275a
"&gt;https://www.okx.com/cn/e...508961a32e58d14da47275a
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;TX after being led by me: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAX6jgKcm1O1gelyLxYvVdIbt9cn3p71T5OwEE4vsaq2Kqar9GSI2Gwkni8-ofmoZZU_9RiTQLik4m-zCTbv7uPhaPJODeyf6PrqNPAS4PWWU4J8kGOKRqcaoAj9xkyOP9kVuIKijntLHM6yGTa5MP1" title="https://www.okx.com/cn/explorer/okc/tx/0x4211418b09571011417257201aaf10fc3c5d638809a9456eb5aba5fe8c5d4e2c
"&gt;https://www.okx.com/cn/e...9a9456eb5aba5fe8c5d4e2c
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We can see that the recipient address is:&lt;br /&gt;```&lt;br /&gt;0x25f0a126be95f437ee71d7c4de725567c5f6c731&lt;br /&gt;```&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150301
" title="https://stocksharp.com/file/150301
"&gt;https://stocksharp.com/file/150301
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To prove that this address is mine, I used this recipient&amp;#39;s address to make a transfer to a black hole address.&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAX6jgKcm1O1gelyLxYvVdIbt9cn3p71T5OwEE4vsaq2JfecK_mM0ziqS3rtK4yva_XtlXA14ijburUf0nWLhR3qJFddj44qUGbM1_ScygDnGvHK4k4qLXI9TIXCHMts_rZyrv_YgKu5ngk_xERoaqZ" title="https://www.okx.com/cn/explorer/okc/tx/0xc32b5e299064456af3eb67c34a3b153f74a1bd18a31429052e3e3c5614bcdb6e
"&gt;https://www.okx.com/cn/e...31429052e3e3c5614bcdb6e
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The black hole address is:&lt;br /&gt;```&lt;br /&gt;0x0000000000000000005757572e464d5a2e434f4d&lt;br /&gt;```&lt;br /&gt;This black hole address contains a URL decoded as:&lt;br /&gt;&lt;br /&gt;```&lt;br /&gt;~ % python -c &amp;#39;print(bytes.fromhex(&amp;quot;0000000000000000005757572e464d5a2e434f4d&amp;quot;))&amp;#39;&lt;br /&gt;b&amp;#39;\x00\x00\x00\x00\x00\x00\x00\x00\x00WWW.FMZ.COM&amp;#39;&lt;br /&gt;```&lt;br /&gt;&amp;gt; Postscript&lt;br /&gt;&lt;br /&gt;This is the end of the story, and in retrospect, I&amp;#39;m grateful for the knowledge I&amp;#39;ve accumulated over the years, otherwise I wouldn&amp;#39;t have been able to crack it so fast and I would have been beaten by others.&lt;br /&gt;I&amp;#39;m sure there was a mistake in the official diagram, but in any case, I was lucky enough to crack the answer before it was made public, and I hope OKX will be more rigorous next time they hold a similar activity.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y66WhudhNiHGehLOUFMNcNd9N4Ud58G8AKhXly4dNcHYiX4uldZ3O2z_A6F-sMcnv_v1c_TmNSCoWn7z089Wavv2ECLpnqCVhbXE7tvbLFUAAqKT_9ccX06apS37JBhbiJw" title="https://blog.mathquant.com/2023/03/16/how-to-solve-the-world-pi-day-okx-private-key-puzzle-award-with-complete-code.html"&gt;https://blog.mathquant.c...-with-complete-code.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25694/</id>
    <title type="text">Digital Currency High-Frequency Strategy Detailed Introduction</title>
    <published>2024-04-16T08:28:19Z</published>
    <updated>2024-04-16T08:28:19Z</updated>
    <author>
      <name>FMZ</name>
      <uri>https://stocksharp.com/users/186354/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#strategy" />
    <category term="#market" />
    <category term="#fmz" />
    <category term="#exchange" />
    <category term="#binance" />
    <category term="#order" />
    <content type="html">I wrote an article in 2020 introducing high-frequency strategies, &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAADHZKb-RfbDOdB_w3dJgQKt-pM0kzoMVMAHLobFcTnU0OSzpfGtRpgBKGhQb2WK-Lc" title="https://www.fmz.com/bbs-topic/9750. "&gt;https://www.fmz.com/bbs-topic/9750. &lt;/a&gt;Although it received quite a bit of attention, it was not very in-depth. More than two years have passed since then, and the market has changed. After that article was published, my high-frequency strategy could make profits stably for a long time, but gradually, the profits declined and even stopped at one point. In recent months I have spent some effort to revamp it, and now it can still make some profits. In this article, I will provide a more detailed introduction to my high-frequency strategy ideas and some simplified code as a starting point for discussion; communications and feedbacks are welcome.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;High-frequency trading conditions&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;- Rebate accounts, taking Binance as an example, it has a maker rebate of 0.0005% currently. If the daily transaction amount is 100 million U, the rebate will be 5000 U. Of course, taker fees are still based on VIP rates, so if the strategy does not require takers, VIP level has little impact on high-frequency strategies. Different levels of exchanges generally have different rebate rates and require maintaining a high transaction amount. In the early times when some currency markets fluctuated greatly, there were profits even without rebates. As competition intensified, rebates accounted for a larger proportion of profits or even relied solely on them; high-frequency traders pursued top-level fees.&lt;br /&gt;&lt;br /&gt;- Speed. The reason why high-frequency strategies are called high-frequency is because they are very fast. Joining the exchange&amp;#39;s colo server, obtaining the lowest latency and most stable connection has also become one of the conditions for internal competition. The internal consumption time of the strategy should be as little as possible, and this article will introduce the websocket framework I use, which adopts concurrent execution.&lt;br /&gt;&lt;br /&gt;- Suitable market. High-frequency trading is known as the pearl of quantitative trading, and many programmatic traders have tried it, but most people stopped because they can&amp;#39;t make profit and can&amp;#39;t find a direction for improvement. The main reason should be that they chose the wrong trading market. In the initial stage of strategy development, relatively easy markets should be chosen to make profits in trading so that there are profits and feedback for improvement, which is conducive to the progress of strategy. If you start competing in the most competitive market with many potential opponents, no matter how hard you try, you will lose money and soon give up. I recommend newly listed perpetual contract trading pairs when there are not so many competitors, especially those with relatively large transaction amount; this is when making profits is easiest. BTC and ETH have the largest transaction amount and are most active in transactions but also hardest to survive.&lt;br /&gt;&lt;br /&gt;- Facing competition. The market for any transaction is changing constantly, and no trading strategy can last forever, especially in high-frequency trading. Entering this market means competing with the smartest and most diligent traders directly. In a zero-sum game market, the more you earn, the less others will earn. The later you enter, the higher the difficulty; those already in the market must also improve continuously. 3-4 years ago was probably the best opportunity; recently, overall activity in digital currency markets has declined, making it very difficult for newcomers to start high-frequency trading now.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;High-frequency principle&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;There are various high-frequency strategies:&lt;br /&gt;&lt;br /&gt;- High-frequency hedging, finding hedging opportunities through this exchange or other exchanges, relying on speed advantage to grab orders and make profits;&lt;br /&gt;- High-frequency trend, making profits by judging short-term trends;&lt;br /&gt;- Market maker, placing orders on both the buying and selling sides, controlling positions well and making profits through the rebates;&lt;br /&gt;- There are many others that I won&amp;#39;t state one by one.&lt;br /&gt;My strategy is a combination of trend and market maker. First, we judge the trend, then place an order. After the transaction is completed, place an order immediately to sell without holding inventory positions. Next, I will introduce it in conjunction with the strategy code.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Strategy framework&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;The following code is based on the basic framework of Binance perpetual contracts, mainly subscribing to websocket depth, depth order flow trades market data, and position information. Since the market data and account information are subscribed separately, it is necessary to use read(-1) continuously to determine whether the latest information has been obtained. Here EventLoop(1000) is used to avoid direct endless loops and reduce system load. EventLoop(1000) will block until there are wss or concurrent task returns with a timeout of 1000ms.&lt;br /&gt;```&lt;br /&gt;var datastream = null&lt;br /&gt;var tickerstream = null&lt;br /&gt;var update_listenKey_time = 0&lt;br /&gt;&lt;br /&gt;function ConncetWss(){&lt;br /&gt;    if (Date.now() - update_listenKey_time &amp;lt; 50*60*1000) {&lt;br /&gt;        return&lt;br /&gt;    }&lt;br /&gt;    if(datastream || tickerstream){&lt;br /&gt;        datastream.close()&lt;br /&gt;        tickerstream.close()&lt;br /&gt;    }&lt;br /&gt;    //Need APIKEY&lt;br /&gt;    let req = HttpQuery(Base+&amp;#39;/fapi/v1/listenKey&amp;#39;, {method: &amp;#39;POST&amp;#39;,data: &amp;#39;&amp;#39;}, null, &amp;#39;X-MBX-APIKEY:&amp;#39; + APIKEY) &lt;br /&gt;    let listenKey = JSON.parse(req).listenKey&lt;br /&gt;    datastream = Dial(&amp;quot;wss://fstream.binance.com/ws/&amp;quot; + listenKey + &amp;#39;|reconnect=true&amp;#39;, 60)&lt;br /&gt;    //Symbols are the set trading pairs&lt;br /&gt;    let trade_symbols_string = Symbols.toLowerCase().split(&amp;#39;,&amp;#39;)&lt;br /&gt;    let wss_url = &amp;quot;wss://fstream.binance.com/stream?streams=&amp;quot;+trade_symbols_string.join(Quote.toLowerCase()+&amp;quot;@aggTrade/&amp;quot;)+Quote.toLowerCase()+&amp;quot;@aggTrade/&amp;quot;+trade_symbols_string.join(Quote.toLowerCase()+&amp;quot;@depth20@100ms/&amp;quot;)+Quote.toLowerCase()+&amp;quot;@depth20@100ms&amp;quot;&lt;br /&gt;    tickerstream = Dial(wss_url+&amp;quot;|reconnect=true&amp;quot;, 60)&lt;br /&gt;    update_listenKey_time = Date.now()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function ReadWss(){&lt;br /&gt;    let data = datastream.read(-1)&lt;br /&gt;    let ticker = tickerstream.read(-1)&lt;br /&gt;    while(data){&lt;br /&gt;        data = JSON.parse(data)&lt;br /&gt;        if (data.e == &amp;#39;ACCOUNT_UPDATE&amp;#39;) {&lt;br /&gt;            updateWsPosition(data)&lt;br /&gt;        }&lt;br /&gt;        if (data.e == &amp;#39;ORDER_TRADE_UPDATE&amp;#39;){&lt;br /&gt;            updateWsOrder(data)&lt;br /&gt;        }        &lt;br /&gt;        data = datastream.read(-1)&lt;br /&gt;    }&lt;br /&gt;    while(ticker){&lt;br /&gt;        ticker = JSON.parse(ticker).data&lt;br /&gt;        if(ticker.e == &amp;#39;aggTrade&amp;#39;){&lt;br /&gt;            updateWsTrades(ticker)&lt;br /&gt;        }&lt;br /&gt;        if(ticker.e == &amp;#39;depthUpdate&amp;#39;){&lt;br /&gt;            updateWsDepth(ticker)&lt;br /&gt;        }&lt;br /&gt;        ticker = tickerstream.read(-1)&lt;br /&gt;    }&lt;br /&gt;    makerOrder()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function main() {&lt;br /&gt;    while(true){&lt;br /&gt;        ConncetWss()&lt;br /&gt;        ReadWss()&lt;br /&gt;        worker()&lt;br /&gt;        updateStatus()&lt;br /&gt;        EventLoop(1000)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Strategy indicators&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;As mentioned earlier, my high-frequency strategy requires determining the trend before executing buying and selling. The short-term trend is mainly judged based on tick-by-tick transaction data, that is, the aggTrade in the subscription, which includes transaction direction, price, quantity, transaction time, etc. Buying and selling mainly refer to depth and trading amount. The following are detailed introductions of the indicators to be concerned about; most of them are divided into buying and selling groups and are counted dynamically within a certain time window. The time window of my strategy is within 10 seconds.&lt;br /&gt;&lt;br /&gt;- Average transaction amount per trade, per trade transactions are the collection of different orders with the same direction and price within 100ms, reflecting the size of buy and sell orders. This data has a high weight, it can be assumed that if the volume of buy orders is greater than sell orders, this is a buyer-dominated market.&lt;br /&gt;- Order frequency or order interval, it is also based on transaction-by-transaction data, the average transaction amount mentioned earlier does not take into account the concept of time and is not entirely accurate. If an order in one direction has a small average transaction amount but a high frequency, it still contributes to the strength of that direction. The average transaction amount * order frequency represents the total transaction amount at fixed intervals and can be used for direct comparison. The arrival of orders follows a Poisson distribution, which can be used to simply estimate how much the total amount of orders arriving within a specific time interval is and provide reference for placing order positions.&lt;br /&gt;- Average spread, this is relatively easy to understand, that is, sell one minus buy one. The current market mostly has a 1-tick spread. If the spread becomes larger, it often means that there is a market trend.&lt;br /&gt;- Average buying and selling price, calculate the average price of each transaction separately, and compare it with the latest price. If the recent purchase order price is higher than the average purchase order price, it can be judged preliminarily that a breakthrough has occurred.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Strategy logic&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Determine short-term trend&lt;/b&gt;&lt;br /&gt;```&lt;br /&gt;//bull represents short-term bullish, bear represents short-term bearish&lt;br /&gt;let bull =  last_sell_price &amp;gt; avg_sell_price &amp;amp;&amp;amp; last_buy_price &amp;gt; avg_buy_price &amp;amp;&amp;amp;&lt;br /&gt;            avg_buy_amount / avg_buy_time &amp;gt; avg_sell_amount / avg_sell_time;&lt;br /&gt;let bear =  last_sell_price &amp;lt; avg_sell_price &amp;amp;&amp;amp; last_buy_price &amp;lt; avg_buy_price &amp;amp;&amp;amp; &lt;br /&gt;            avg_buy_amount / avg_buy_time &amp;lt; avg_sell_amount / avg_sell_time;&lt;br /&gt;```&lt;br /&gt;If the latest selling price is higher than the average selling price, the latest buying price is higher than the average buying price, and the fixed interval buying order value is greater than the selling order value, then it is judged to be short-term bullish. Conversely, it&amp;#39;s bearish.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Price for placing orders&lt;/b&gt;&lt;br /&gt;```&lt;br /&gt;function updatePrice(depth, bid_amount, ask_amount) {&lt;br /&gt;&lt;br /&gt;    let buy_price = 0&lt;br /&gt;    let sell_price = 0&lt;br /&gt;    let acc_bid_amount = 0&lt;br /&gt;    let acc_ask_amount = 0&lt;br /&gt;&lt;br /&gt;    for (let i = 0; i &amp;lt; Math.min(depth.asks.length, depth.bids.length); i++) {&lt;br /&gt;        acc_bid_amount += parseFloat(depth.bids[i][1])&lt;br /&gt;        acc_ask_amount += parseFloat(depth.asks[i][1])&lt;br /&gt;        if (acc_bid_amount &amp;gt; bid_amount  &amp;amp;&amp;amp; buy_price == 0) {&lt;br /&gt;            buy_price = parseFloat(depth.bids[i][0]) + tick_size&lt;br /&gt;        }&lt;br /&gt;        if (acc_ask_amount &amp;gt; ask_amount  &amp;amp;&amp;amp; sell_price == 0) {&lt;br /&gt;            sell_price = parseFloat(depth.asks[i][0]) - tick_size&lt;br /&gt;        }&lt;br /&gt;        if (buy_price &amp;gt; 0 &amp;amp;&amp;amp; sell_price &amp;gt; 0) {&lt;br /&gt;            break&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    return [buy_price, sell_price]&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;Here, we still adopt the old approach, iterating to the required depth. Assuming that 10 coins can be traded in 1 second, without considering new pending orders, the selling price is set at the position where 10 coins are bought. The specific size of the time window needs to be set by yourself.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Order amount&lt;/b&gt;&lt;br /&gt;```&lt;br /&gt;let buy_amount = Ratio * avg_sell_amount / avg_sell_time&lt;br /&gt;let sell_amount = Ratio * avg_buy_amount / avg_buy_time&lt;br /&gt;```&lt;br /&gt;Ratio represents a fixed proportion, which means that the buy order quantity is a fixed proportion of the recent sell order quantity. In this way, the strategy can adjust the order size adaptively according to the current buying and selling activity.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Place order conditions&lt;/b&gt;&lt;br /&gt;```&lt;br /&gt;if(bull &amp;amp;&amp;amp; (sell_price-buy_price) &amp;gt; N * avg_diff) {&lt;br /&gt;    trade(&amp;#39;buy&amp;#39;, buy_price, buy_amount)&lt;br /&gt;}else if(position.amount &amp;lt; 0){&lt;br /&gt;    trade(&amp;#39;buy&amp;#39;, buy_price, -position.amount)&lt;br /&gt;}&lt;br /&gt;if(bear &amp;amp;&amp;amp; (sell_price-buy_price) &amp;gt;  N * avg_diff) {&lt;br /&gt;    trade(&amp;#39;sell&amp;#39;, sell_price, sell_amount)&lt;br /&gt;}else if(position.amount &amp;gt; 0){&lt;br /&gt;    trade(&amp;#39;sell&amp;#39;, sell_price, position.amount)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;Where avg_diff is the average market price difference, and a buy order will only be placed when the bid-ask spread is greater than a certain multiple of this value and it&amp;#39;s bullish. If holding a short position, it will also close the position to avoid holding for an extended period. Orders can be placed as only-maker orders to ensure they are executed. Additionally, Binance&amp;#39;s custom order ID can be used so that there is no need to wait for the order response.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Concurrent structure&lt;/b&gt;&lt;br /&gt;```&lt;br /&gt;var tasks = []&lt;br /&gt;var jobs = []&lt;br /&gt;&lt;br /&gt;function worker(){&lt;br /&gt;    let new_jobs = []&lt;br /&gt;    for(let i=0; i&amp;lt;tasks.length; i++){&lt;br /&gt;        let task = tasks[i]&lt;br /&gt;        jobs.push(exchange.Go.apply(this, task.param))&lt;br /&gt;    }&lt;br /&gt;    _.each(jobs, function(t){&lt;br /&gt;        let ret = t.wait(-1)&lt;br /&gt;        if(ret === undefined){&lt;br /&gt;            new_jobs.push(t)//Unreturned tasks will continue to wait next time&lt;br /&gt;        }&lt;br /&gt;    })&lt;br /&gt;    jobs = new_jobs&lt;br /&gt;    tasks = []&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;Write the required task parameters in param&lt;br /&gt;tasks.push({&amp;#39;type&amp;#39;:&amp;#39;order&amp;#39;,&amp;#39;param&amp;#39;: [&amp;quot;IO&amp;quot;, &amp;quot;api&amp;quot;, &amp;quot;POST&amp;quot;,&amp;quot;/fapi/v1/order&amp;quot;,&lt;br /&gt;        &amp;quot;symbol=&amp;quot;+symbol+Quote+&amp;quot;&amp;amp;side=&amp;quot;+side+&amp;quot;&amp;amp;type=LIMIT&amp;amp;timeInForce=GTX&amp;amp;quantity=&amp;quot;+&lt;br /&gt;        amount+&amp;quot;&amp;amp;price=&amp;quot;+price+&amp;quot;&amp;amp;newClientOrderId=&amp;quot; + UUID() +&amp;quot;&amp;amp;timestamp=&amp;quot;+Date.now()]})&lt;br /&gt;*/&lt;br /&gt;```&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Monitored data&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;- Delay, the importance of high-frequency strategy speed has been emphasized. In the strategy, various delays need to be monitored and recorded, such as placing orders, canceling orders, position returns, depth, order flow, positions, overall loops and so on. Any abnormal delays should be investigated in time and try to shorten the overall strategy delay.&lt;br /&gt;- Transaction amount ratio, calculate the transaction amount as a percentage of the total transaction amount. If the ratio is low, there is still room for growth. At peak times, it is possible for the strategy to account for more than 10% of the total trading amount.&lt;br /&gt;- Profit rate of closing positions, calculating the average closing position profit rate is the most important reference for judging whether a strategy is effective.&lt;br /&gt;- Rebate ratio, the proportion of rebates in total revenue, reflects the degree of reliance on rebates by the strategy. Exchange platforms have different rebate levels, and unprofitable strategies may be profitable with a higher level of rebate.&lt;br /&gt;- Placing order failure rate, orders are only traded by placing an order. Due to the delay in placing an order, it may not be placed. If this ratio is high, it means that the strategy&amp;#39;s speed is not advantageous.&lt;br /&gt;- The proportion of completed orders, platforms often have requirements for the transaction rate. If it is too low, it means that the strategy cancels orders too frequently and needs to be resolved.&lt;br /&gt;- Average buying and selling order distance, which reflects the strategy of placing orders and the gap between the market, we can see that most of them still occupy the position of buying one and selling one.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Other suggestions&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;- Trade multiple currencies, the high-frequency strategy in this article only refers to a single exchange, single currency and single market. It has great limitations, and most situations and currencies cannot make profits. However, it is impossible to predict which currency will be profitable in the future, so you can trade multiple or even all currencies without missing opportunities. Even under the frequency limit of exchanges, a robot can trade multiple trading pairs. Of course, for optimal speed, one sub-account can trade one trading pair with one server corresponding to one robot; however, this would result in much higher costs.&lt;br /&gt;- Determine the order quantity and order conditions based on the yield. Trading with multiple currencies will result in high cost of attempts, if monitoring is not profitable, use the minimum transaction amount and reduce the trading frequency until the strategy dynamically monitors a positive return rate, then increase the transaction amount to improve returns gradually.&lt;br /&gt;- Obtain more information, another feature of high-frequency trading is that it processes a larger amount of data and uses more information. All market information for a single trading pair within a single exchange should be referenced, and perpetual contracts can also refer to spot market data, as well as data from other exchanges for the same trading pair, or even data from other currencies. The more data there is, the greater the corresponding advantage. For example, Binance can subscribe to the best pending order information by Symbol, because the shortest push time for depth and order flow is 100ms; only this is real-time and very valuable for high-frequency strategies.&lt;br /&gt;- Binance&amp;#39;s server is in aws Tokyo, other exchanges&amp;#39; servers vary, you can consult the technical staff of the exchange for details.&lt;br /&gt;- The strategy code in this article is just a simplified example code, with many cumbersome but necessary details removed. The indicators used are for reference only and should not be used directly. There are many details to pay attention to when running a high-frequency strategy, and it requires patience to modify and improve.&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y6333FTg-10w2rr57aj1qBbPj8pfKgzNw117UIdW8HnHV88d2PpETdtQID6SJ6M7SIIHoctE-O_htKMYPmMQZyWlE5omJ-qP_HuJfhQllT7nq" title="https://blog.mathquant.com/2023/03/27/digital-currency-high-frequency-strategy-detailed-introduction.html"&gt;https://blog.mathquant.c...tailed-introduction.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25693/</id>
    <title type="text">How ChatGPT improves your quantitative productivity significantly</title>
    <published>2024-04-16T06:42:59Z</published>
    <updated>2024-04-16T06:42:59Z</updated>
    <author>
      <name>FMZ</name>
      <uri>https://stocksharp.com/users/186354/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#code" />
    <category term="#robot" />
    <category term="#algorithm" />
    <category term="#FMZQuant" />
    <category term="#programming" />
    <category term="#fintec" />
    <category term="#automation" />
    <category term="#ChatGPT" />
    <content type="html">For quantitative trading and programmatic trading beginners, what are the biggest difficulties in learning? Generally speaking, there are several reasons:&lt;br /&gt;&lt;br /&gt;- Basic knowledge deficiency: including basic concepts, market rules, trading knowledge, strategic thinking, etc.&lt;br /&gt;- Poor programming foundation: including logical expression, program design and writing, program debugging and error correction.&lt;br /&gt;- Weak logical thinking: the process of thinking can cause confusion easily, and the more you think, the more confused you become.&lt;br /&gt;- Self-study difficulties: When encountering problems, it is difficult to know where to start solving them, and the direction of problem searching may not even be clear.&lt;br /&gt;&lt;br /&gt;With the development of AI technology, solutions to these problems can be found to some extent. The recently popular **ChatGPT** can be used as a tool for quantitative trading learning, research, and creation. With FMZ platform&amp;#39;s new upgrade for strategy editor and integration with ChatGPT, it improves the productivity of quantification greatly. Let&amp;#39;s explore **the new functions of FMZ strategy editor** together!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Use ChatGPT to assist in code design&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Although the current capabilities of ChatGPT are already very powerful, and it can understand human questions very well, the answers it provides are still highly sensitive to factors such as **the completeness and accuracy of the question description**. If the described scenario or question content is not accurate, ChatGPT may be unable to provide a perfect answer. Therefore, when using it to solve some problems, it is necessary to try to express them correctly and completely.&lt;br /&gt;&lt;br /&gt;Next, we will use the ChatGPT function of the FMZ platform strategy editor to solve a code design problem. Log in to the FMZ platform and go to the strategy editing page.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;1. Summon ChatGPT&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150281
" title="https://stocksharp.com/file/150281
"&gt;https://stocksharp.com/file/150281
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Right-click on the blank space, select ChatGPT option and click to call out ```ChatGPT```, or **use Ctrl+K to call out ChatGPT**.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;2. The technique of asking questions&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;If I am a quantitative trading beginner now, I have a requirement:&lt;br /&gt;&lt;br /&gt; &amp;gt; Use one-minute K-line to synthesize any period K-line data.&lt;br /&gt;&lt;br /&gt;As a beginner, my programming ability is poor, and I really don&amp;#39;t know how to write such an algorithm. In the past, I could only search for information and ask experts for help. Now, with ChatGPT, I can ask it for answers directly. Of course, as mentioned above, describing the requirement directly: &amp;quot;**Use one-minute K-line data to synthesize any period K-line data**&amp;quot;. GPT is unlikely to give you a 100% usable answer, so you still need to try your best to describe the problem thoroughly. Taking the requirement as an example, I kept adjusting my questions and asked many times before getting a usable answer that met my needs.&lt;br /&gt;&lt;br /&gt;So let&amp;#39;s make this requirement description a little more complete:&lt;br /&gt;```&lt;br /&gt; &amp;gt; On the FMZ platform, calling the exchange.GetRecords(60) function can obtain one-minute K-line data, and the data structure is: [{&lt;br /&gt; &amp;gt; Time : Millisecond timestamp, // Start time of the period&lt;br /&gt; &amp;gt; Open : 1000,&lt;br /&gt; &amp;gt; High : 1500,&lt;br /&gt; &amp;gt; Low : 900,&lt;br /&gt; &amp;gt; Close : 1200,&lt;br /&gt; &amp;gt; Volume : 1000000&lt;br /&gt; &amp;gt; }, ...]&lt;br /&gt; &amp;gt; Please design an algorithm that uses one-minute K-line data to synthesize any minute&amp;#39;s K-line data. For periods that can be divided by 60 minutes, start counting from the whole point of 0 minutes. Implement it in Javascript language, write this algorithm as a separate function, test it in the function main() and use $.PlotRecords(KLineData, &amp;quot;name&amp;quot;) for drawing.&lt;br /&gt;```&lt;br /&gt;After calling out ChatGPT, you can fill in the optimized question content mentioned above.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150282
" title="https://stocksharp.com/file/150282
"&gt;https://stocksharp.com/file/150282
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ChatGPT starts working.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150284
" title="https://stocksharp.com/file/150284
"&gt;https://stocksharp.com/file/150284
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wait for it to finish writing.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150283
" title="https://stocksharp.com/file/150283
"&gt;https://stocksharp.com/file/150283
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Sometimes ```ChatGPT``` adds ``` symbols to wrap the code, which in markdown indicates that the wrapped content is code. So we just need to remove the first and last lines. Since I asked it to use ```$.PlotRecords(KLineData, &amp;quot;name&amp;quot;)``` for drawing, the strategy needs to reference a drawing library in order to draw. The purpose of drawing is to verify whether the K-line data synthesized by Chat GPT&amp;#39;s code is correct.&lt;br /&gt;Regarding what a template library is, I will not elaborate here; you can refer to FMZ&amp;#39;s API documentation for more information, [The address of the Plot Library](https://www.fmz.com/strategy/27293).&lt;br /&gt;&lt;br /&gt;The code provided by ```ChatGPT``` can be backtested directly. I set the default K-line period of the backtesting system as 5 minutes, which is used for comparing with K-line charts drawn from K-line data calculated by Chat GPT&amp;#39;s algorithm.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150285
" title="https://stocksharp.com/file/150285
"&gt;https://stocksharp.com/file/150285
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;3. Backtest test code given by ChatGPT&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150287
" title="https://stocksharp.com/file/150287
"&gt;https://stocksharp.com/file/150287
&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150286
" title="https://stocksharp.com/file/150286
"&gt;https://stocksharp.com/file/150286
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Preliminarily, it seems that the algorithm given by ChatGPT to synthesize 5-minute K-line from 1-minute K-line is correct.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;4. Complete code written by ChatGPT:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;```&lt;br /&gt;/*&lt;br /&gt;Synthesize arbitrary minute K-line data&lt;br /&gt;@param {Array} records - One-minute K-line data&lt;br /&gt;@param {Number} period - Synthetic period, unit in minutes&lt;br /&gt;@return {Array} - Synthesized K-line data&lt;br /&gt;*/&lt;br /&gt;function composeKLineData(records, period) {&lt;br /&gt;  var result = [];&lt;br /&gt;  var index = 0;&lt;br /&gt;  var open = records[0].Open;&lt;br /&gt;  var high = records[0].High;&lt;br /&gt;  var low = records[0].Low;&lt;br /&gt;  var close = records[0].Close;&lt;br /&gt;  var volume = records[0].Volume;&lt;br /&gt;  var time = records[0].Time - records[0].Time % (period * 60 * 1000);&lt;br /&gt;  for (var i = 1; i &amp;lt; records.length; i++) {&lt;br /&gt;    var record = records[i];&lt;br /&gt;    if (record.Time &amp;lt; time + period * 60 * 1000) {&lt;br /&gt;      high = Math.max(high, record.High);&lt;br /&gt;      low = Math.min(low, record.Low);&lt;br /&gt;      close = record.Close;&lt;br /&gt;      volume += record.Volume;&lt;br /&gt;    } else {&lt;br /&gt;      result[index] = {&lt;br /&gt;        Time: time,&lt;br /&gt;        Open: open,&lt;br /&gt;        High: high,&lt;br /&gt;        Low: low,&lt;br /&gt;        Close: close,&lt;br /&gt;        Volume: volume&lt;br /&gt;      };&lt;br /&gt;      index++;&lt;br /&gt;      open = record.Open;&lt;br /&gt;      high = record.High;&lt;br /&gt;      low = record.Low;&lt;br /&gt;      close = record.Close;&lt;br /&gt;      volume = record.Volume;&lt;br /&gt;      time = record.Time - record.Time % (period * 60 * 1000);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  result[index] = {&lt;br /&gt;    Time: time,&lt;br /&gt;    Open: open,&lt;br /&gt;    High: high,&lt;br /&gt;    Low: low,&lt;br /&gt;    Close: close,&lt;br /&gt;    Volume: volume&lt;br /&gt;  };&lt;br /&gt;  return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function main() {&lt;br /&gt;  var records = exchange.GetRecords(60);&lt;br /&gt;  var kLineData = composeKLineData(records, 5); // Synthesize 5-minute K-line data&lt;br /&gt;  $.PlotRecords(kLineData, &amp;quot;KLineData&amp;quot;);&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Use ChatGPT to explain code&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;FMZ&amp;#39;s integrated ChatGPT not only helps you write code, but also helps you explain the code. Select the ```composeKLineData``` function in the code just written by ChatGPT, right-click to show the menu:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150289
" title="https://stocksharp.com/file/150289
"&gt;https://stocksharp.com/file/150289
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Use ChatGPT to give suggestions and optimize code&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Even ChatGPT can provide optimization suggestions and optimized code.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150288
" title="https://stocksharp.com/file/150288
"&gt;https://stocksharp.com/file/150288
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Other functions added to the editor&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;The FMZ editor update, in addition to adding the ChatGPT function. It also optimizes and enhances the online programming experience, adding many convenient functions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;View shortcut combinations&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Right-click in the blank space or when selecting code to show the menu.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150290
" title="https://stocksharp.com/file/150290
"&gt;https://stocksharp.com/file/150290
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It displays various shortcut key combinations.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150292
" title="https://stocksharp.com/file/150292
"&gt;https://stocksharp.com/file/150292
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Modify variable name&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Rename Symbol to modify the local variable name.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150291
" title="https://stocksharp.com/file/150291
"&gt;https://stocksharp.com/file/150291
&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150294
" title="https://stocksharp.com/file/150294
"&gt;https://stocksharp.com/file/150294
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It only changed the variable name ```records``` in the ```main``` function of the above picture.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Modify all the same content&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Change All Occurrences, select a variable name, word, and edit all the same content in the text simultaneously.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150293
" title="https://stocksharp.com/file/150293
"&gt;https://stocksharp.com/file/150293
&lt;/a&gt;&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150297
" title="https://stocksharp.com/file/150297
"&gt;https://stocksharp.com/file/150297
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Formatting (code optimization, automatic alignment format)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Format Selection, format the selected code.&lt;br /&gt;&lt;br /&gt;Format Document, format all code.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150296
" title="https://stocksharp.com/file/150296
"&gt;https://stocksharp.com/file/150296
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%"&gt;&lt;b&gt;Go to Definition, Reference&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Go to Definition: Go to Definition.&lt;br /&gt;Go to References: Go to References.&lt;br /&gt;Go to Symbol...: Go to variable names, function names, etc.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150295
" title="https://stocksharp.com/file/150295
"&gt;https://stocksharp.com/file/150295
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:140%"&gt;Peek Definition, Peek References&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Peek Definition: Definition preview, view the definition of the selected code without leaving the current line of code.&lt;br /&gt;Peek References: Quote preview, view the references to the current code line in other code lines without leaving the current code line, it can go quickly, in order to understand the code logic and structure better.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150298
" title="https://stocksharp.com/file/150298
"&gt;https://stocksharp.com/file/150298
&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y607EV_25KicVAAZ7UuJY6k8hfJvkdG6_rKXLz69gjS0ajpYPIocWa-_NgA01I46Son75fgK4aY1VPc_q4joU_7pHEEgNyVypRixcmBHaIsjXzWe4h7sPPYIw9pAIskthBOCNFFVzQIaDiiXgLgRyUwkgytafUddh7kIUeY5yJuJa" title="https://blog.mathquant.com/2023/04/03/explore-the-new-functions-of-fmz-strategy-editor-how-chatgpt-improves-your-quantitative-productivity-significantly.html"&gt;https://blog.mathquant.c...ivity-significantly.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25692/</id>
    <title type="text">Get Started with web3 Development Easily Based on Ethereum Using FMZ (7)</title>
    <published>2024-04-16T05:12:05Z</published>
    <updated>2024-04-16T05:12:05Z</updated>
    <author>
      <name>FMZ</name>
      <uri>https://stocksharp.com/users/186354/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#code" />
    <category term="#data" />
    <category term="#market" />
    <category term="#fmz" />
    <category term="#Ethereum" />
    <category term="#token" />
    <category term="#web3" />
    <category term="#address" />
    <category term="#wallet" />
    <content type="html">### Execute Read method calldata&lt;br /&gt;&lt;br /&gt;For the execution of the ```calldata``` of the Read method, we use the previously learned RPC method: ```eth_call``` to execute it. We explained the ```eth_call``` RPC method of the Ethereum only did a demonstration of the ```Write``` method of the smart contract, in this section, we use the ```calldata``` method to demonstrate the execution of the smart contract Read method call. Let&amp;#39;s use the ```balanceOf``` method of the WETH contract to read the current balance of WETH tokens in the wallet.&lt;br /&gt;&lt;br /&gt;We use the debugging tool to test on the Ethereum mainnet at:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function toAmount(s, decimals) {&lt;br /&gt;    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())&lt;br /&gt;}&lt;br /&gt;function main() {&lt;br /&gt;    // ABI for WETH contracts&lt;br /&gt;    var abiWETH = `[{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;name&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;string&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;guy&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approve&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bool&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;totalSupply&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;src&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;dst&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;transferFrom&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bool&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;withdraw&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;decimals&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;balanceOf&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;symbol&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;string&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;dst&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;transfer&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bool&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;deposit&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;payable&amp;quot;:true,&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;allowance&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;payable&amp;quot;:true,&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;fallback&amp;quot;},{&amp;quot;anonymous&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;src&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;guy&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:false,&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;Approval&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;event&amp;quot;},{&amp;quot;anonymous&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;src&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;dst&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:false,&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;Transfer&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;event&amp;quot;},{&amp;quot;anonymous&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;dst&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:false,&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;Deposit&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;event&amp;quot;},{&amp;quot;anonymous&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;src&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:false,&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;Withdrawal&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;event&amp;quot;}]`&lt;br /&gt;&lt;br /&gt;    // WETH contract address&lt;br /&gt;    var wethAddress = &amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;&lt;br /&gt;&lt;br /&gt;    // Register ABI for WETH contracts&lt;br /&gt;    exchange.IO(&amp;quot;abi&amp;quot;, wethAddress, abiWETH)&lt;br /&gt;&lt;br /&gt;    // The wallet address of the currently configured exchange object&lt;br /&gt;    var walletAddress = exchange.IO(&amp;quot;address&amp;quot;)&lt;br /&gt;&lt;br /&gt;    // Coded WETH contract&amp;#39;s deposit method call&lt;br /&gt;    var calldataForDeposit = exchange.IO(&amp;quot;encode&amp;quot;, wethAddress, &amp;quot;balanceOf(address)&amp;quot;, walletAddress)&lt;br /&gt;    Log(&amp;quot;calldataForDeposit:&amp;quot;, &amp;quot;0x&amp;quot; + calldataForDeposit)&lt;br /&gt;&lt;br /&gt;    // Construct the transaction as the first parameter of eth_call&lt;br /&gt;    var transaction = {&lt;br /&gt;        &amp;quot;from&amp;quot; : walletAddress,&lt;br /&gt;        &amp;quot;to&amp;quot; : wethAddress,&lt;br /&gt;        &amp;quot;data&amp;quot; : &amp;quot;0x&amp;quot; + calldataForDeposit,&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // The second parameter of eth_call&lt;br /&gt;    var blockNumber = &amp;quot;latest&amp;quot;&lt;br /&gt;&lt;br /&gt;    // Call with eth_call&lt;br /&gt;    var ret = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_call&amp;quot;, transaction, blockNumber)&lt;br /&gt;    var wethBalance = exchange.IO(&amp;quot;decode&amp;quot;, &amp;quot;uint256&amp;quot;, ret)   // You can use exchange.IO(&amp;quot;decode&amp;quot;, ...) function to decode&lt;br /&gt;    Log(&amp;quot;wethBalance:&amp;quot;, toAmount(wethBalance, 18))            // Converted from wei to WETH units&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Run in the debugging tool:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-15 11:51:31		Info	wethBalance: 0.015&lt;br /&gt;2023-06-15 11:51:31		Info	calldataForDeposit: 0x70a082310000000000000000000000006b3f11d807809b0b1e5e3243df04a280d9f94bf4&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;If the method of a smart contract has a return value, you can use the ```exchange.IO(&amp;quot;decode&amp;quot;, ...)``` function to decode it. You can see that the passing ```calldata``` method is the same as calling the smart contract&amp;#39;s ```balanceOf``` method directly, getting the WETH balance of 0.015 WETH for my test wallet.&lt;br /&gt;&lt;br /&gt;### Execute Write method calldata&lt;br /&gt;&lt;br /&gt;For the execution of the Write method calldata, it is necessary to use the RPC method: ```eth_sendRawTransaction```.&lt;br /&gt;&lt;br /&gt;Let&amp;#39;s use the debugging tool and test it on the Ethereum mainnet at:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function toAmount(s, decimals) {&lt;br /&gt;    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())&lt;br /&gt;}&lt;br /&gt;function toInnerAmount(s, decimals) {&lt;br /&gt;    return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)&lt;br /&gt;}&lt;br /&gt;function main() {&lt;br /&gt;    // ABI for WETH contracts&lt;br /&gt;    var abiWETH = `[{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;name&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;string&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;guy&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approve&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bool&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;totalSupply&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;src&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;dst&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;transferFrom&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bool&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;withdraw&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;decimals&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;balanceOf&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;symbol&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;string&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;dst&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;transfer&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bool&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:false,&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;deposit&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;payable&amp;quot;:true,&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;constant&amp;quot;:true,&amp;quot;inputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;allowance&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;payable&amp;quot;:false,&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;payable&amp;quot;:true,&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;fallback&amp;quot;},{&amp;quot;anonymous&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;src&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;guy&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:false,&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;Approval&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;event&amp;quot;},{&amp;quot;anonymous&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;src&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;dst&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:false,&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;Transfer&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;event&amp;quot;},{&amp;quot;anonymous&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;dst&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:false,&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;Deposit&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;event&amp;quot;},{&amp;quot;anonymous&amp;quot;:false,&amp;quot;inputs&amp;quot;:[{&amp;quot;indexed&amp;quot;:true,&amp;quot;name&amp;quot;:&amp;quot;src&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;indexed&amp;quot;:false,&amp;quot;name&amp;quot;:&amp;quot;wad&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;Withdrawal&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;event&amp;quot;}]`&lt;br /&gt;&lt;br /&gt;    // WETH contract address&lt;br /&gt;    var wethAddress = &amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;&lt;br /&gt;&lt;br /&gt;    // Register ABI for WETH contract&lt;br /&gt;    exchange.IO(&amp;quot;abi&amp;quot;, wethAddress, abiWETH)&lt;br /&gt;&lt;br /&gt;    // The wallet address of the currently configured exchange object&lt;br /&gt;    var walletAddress = exchange.IO(&amp;quot;address&amp;quot;)&lt;br /&gt;&lt;br /&gt;    // Coded WETH contract&amp;#39;s deposit method call&lt;br /&gt;    var calldataForDeposit = exchange.IO(&amp;quot;encode&amp;quot;, wethAddress, &amp;quot;deposit&amp;quot;)&lt;br /&gt;    Log(&amp;quot;calldataForDeposit:&amp;quot;, &amp;quot;0x&amp;quot; + calldataForDeposit)&lt;br /&gt;&lt;br /&gt;    // Get nonce&lt;br /&gt;    var nonce = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getTransactionCount&amp;quot;, walletAddress, &amp;quot;pending&amp;quot;)&lt;br /&gt;&lt;br /&gt;    // Get gasPrice&lt;br /&gt;    var gasPrice = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_gasPrice&amp;quot;)&lt;br /&gt;&lt;br /&gt;    // Call the deposit method to change ETH to WETH, you need to transfer ETH, here we convert 0.01ETH to a hexadecimal value in wei&lt;br /&gt;    var innerAmount = BigInt(Number(toInnerAmount(0.005, 18))).toString(16)&lt;br /&gt;&lt;br /&gt;    // The transaction call object:&lt;br /&gt;    var obj = {&lt;br /&gt;        &amp;quot;from&amp;quot; : walletAddress,&lt;br /&gt;        &amp;quot;to&amp;quot;  : wethAddress,&lt;br /&gt;        &amp;quot;gasPrice&amp;quot; : gasPrice,&lt;br /&gt;        &amp;quot;value&amp;quot; : &amp;quot;0x&amp;quot; + innerAmount,&lt;br /&gt;        &amp;quot;data&amp;quot; : &amp;quot;0x&amp;quot; + calldataForDeposit,&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Calculate gasLimit&lt;br /&gt;    var gasLimit = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_estimateGas&amp;quot;, obj)&lt;br /&gt;&lt;br /&gt;    // Construct a transaction&lt;br /&gt;    var transaction = {&lt;br /&gt;        &amp;quot;to&amp;quot;: wethAddress,&lt;br /&gt;        &amp;quot;value&amp;quot;: toAmount(&amp;quot;0x&amp;quot; + innerAmount, 0),   // Convert to decimal&lt;br /&gt;        &amp;quot;data&amp;quot;: &amp;quot;0x&amp;quot; + calldataForDeposit,&lt;br /&gt;        &amp;quot;gasLimit&amp;quot;: toAmount(gasLimit, 0),   // Convert to decimal&lt;br /&gt;        &amp;quot;gasPrice&amp;quot;: toAmount(gasPrice, 0),   // Convert to decimal&lt;br /&gt;        &amp;quot;nonce&amp;quot;: toAmount(nonce, 0),         // Convert to decimal&lt;br /&gt;        &amp;quot;chainId&amp;quot;: 1,                        // Ethereum mainnet Id&lt;br /&gt;    }&lt;br /&gt;    Log(&amp;quot;transaction:&amp;quot;, transaction)&lt;br /&gt;&lt;br /&gt;    // Signature, your key is replaced with your private key&lt;br /&gt;    var signedTx = Encode(&amp;quot;signTx&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;hex&amp;quot;, JSON.stringify(transaction), &amp;quot;hex&amp;quot;, &amp;quot;0x&amp;quot; + &amp;quot;your key&amp;quot;)&lt;br /&gt;    Log(&amp;quot;signedTx:&amp;quot;, &amp;quot;0x&amp;quot; + signedTx)&lt;br /&gt;&lt;br /&gt;    // Call eth_sendRawTransaction to send a transaction&lt;br /&gt;    var ret = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_sendRawTransaction&amp;quot;, &amp;quot;0x&amp;quot; + signedTx)&lt;br /&gt;    return ret &lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Run in the debugging tool:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-15 09:58:50		Info	signedTx: 0xf86f4f8504202067888...&lt;br /&gt;2023-06-15 09:58:50		Info	transaction: {&amp;quot;to&amp;quot;:&amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;,&amp;quot;value&amp;quot;:5000000000000000,&amp;quot;data&amp;quot;:&amp;quot;0xd0e30db0&amp;quot;,&amp;quot;gasLimit&amp;quot;:27938,&amp;quot;gasPrice&amp;quot;:17718863752,&amp;quot;nonce&amp;quot;:79,&amp;quot;chainId&amp;quot;:1}&lt;br /&gt;2023-06-15 09:58:50		Info	calldataForDeposit: 0xd0e30db0&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Execute ```var ret = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_sendRawTransaction&amp;quot;, &amp;quot;0x&amp;quot; + signedTx)``` function and the returned Transaction Hash is: ``` 0x2ff585504b0fe59b0122f696e8808abfe2f3ce263448066533f3bb8a4f55e8e6```. The ```eth_sendRawTransaction``` call executes the calldata in it, calling the ```deposit``` method of the WETH contract to swap the 0.005 ETH sent for WETH.&lt;br /&gt;&lt;br /&gt;## Listening to mempool&lt;br /&gt;&lt;br /&gt;Before a user&amp;#39;s transaction is packaged into the Ethereum blockchain by miners, all transactions will be pooled in ```Mempool``` (transaction memory pool), where &amp;quot;miners&amp;quot; also look for transactions with high fees to be packaged first, in order to maximize mining benefits. Therefore, usually the higher the transaction&amp;#39;s gasPrice setting, the more likely it is to be packaged.&lt;br /&gt;&lt;br /&gt;Some transaction scripts will also sniff ```Mempool``` in the hope of finding some profitable transactions. For example, if a transaction is set with a high exchange slippage, the transaction could be subject to a &amp;quot;sandwich attack&amp;#39;&amp;#39; by these transactionscripts. So how do these scripts listen for ```pending``` (pending, to-be-packaged) transactions in ```Mempool```?&lt;br /&gt;&lt;br /&gt;### Listening with the REST protocol&lt;br /&gt;&lt;br /&gt;Use the RPC method we learned before: ```eth_getBlockByNumber```, but we do not pass the specific ```blockNumber``` this time, we use the ```&amp;quot;pending&amp;quot;``` tag.&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    var data = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getBlockByNumber&amp;quot;, &amp;quot;pending&amp;quot;, true)&lt;br /&gt;    if (Array.isArray(data.transactions)) {&lt;br /&gt;        for (var i = 0; i &amp;lt; data.transactions.length; i++) {&lt;br /&gt;            Log(data.transactions[i])&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Run in the debugging tool:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-18 19:23:05		Info	{&amp;quot;blockNumber&amp;quot;:&amp;quot;0x10b2027&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;0x2&amp;quot;,&amp;quot;accessList&amp;quot;:[],&amp;quot;blockHash&amp;quot;:&amp;quot;0xf833ed36435c53d63bd7109bb1e85383075534410c14573881bf26d912f46a89&amp;quot;,&amp;quot;from&amp;quot;:&amp;quot;0xd50521974d62f1fa34b8e81cb742ccf6147d05ff&amp;quot;,&amp;quot;gasPrice&amp;quot;:&amp;quot;0x32ea2db37&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0xf8f10f8f473c340b021298feb48d0affe529e8737a309c4cc1902e8989ef0914&amp;quot;,&amp;quot;input&amp;quot;:&amp;quot;0xa22cb4650000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000000000000000000000000000000000000000000000000000000000000001&amp;quot;,&amp;quot;v&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;maxFeePerGas&amp;quot;:&amp;quot;0x48a413364&amp;quot;,&amp;quot;maxPriorityFeePerGas&amp;quot;:&amp;quot;0x5f5e100&amp;quot;,&amp;quot;nonce&amp;quot;:&amp;quot;0x8&amp;quot;,&amp;quot;r&amp;quot;:&amp;quot;0x8c1cc36f43b02c9e9e454153588cc9d38757f1da69ec49d3cfdda74ab69e06a8&amp;quot;,&amp;quot;s&amp;quot;:&amp;quot;0x2f3dd3e5ddf9e5d42c128a8e900026aca7568fa83c68cf332e1328066ee8d03a&amp;quot;,&amp;quot;transactionIndex&amp;quot;:&amp;quot;0x3a&amp;quot;,&amp;quot;chainId&amp;quot;:&amp;quot;0x1&amp;quot;,&amp;quot;gas&amp;quot;:&amp;quot;0x1142d&amp;quot;,&amp;quot;to&amp;quot;:&amp;quot;0x8c3c0274c33f263f0a55d129cfc8eaa3667a9e8b&amp;quot;}&lt;br /&gt;2023-06-18 19:23:05		Info	{&amp;quot;input&amp;quot;:&amp;quot;0x646174613a2c7b2270223a226572632d3230222c226f70223a226d696e74222c227469636b223a2265746873222c226964223a223139323732222c22616d74223a2231303030227d&amp;quot;,&amp;quot;nonce&amp;quot;:&amp;quot;0x1d&amp;quot;,&amp;quot;blockHash&amp;quot;:&amp;quot;0xf833ed36435c53d63bd7109bb1e85383075534410c14573881bf26d912f46a89&amp;quot;,&amp;quot;from&amp;quot;:&amp;quot;0xe7fa86855af674837cea1b58f88b5352543ca27b&amp;quot;,&amp;quot;gas&amp;quot;:&amp;quot;0x81cc&amp;quot;,&amp;quot;gasPrice&amp;quot;:&amp;quot;0x32ea2db37&amp;quot;,&amp;quot;to&amp;quot;:&amp;quot;0xe7fa86855af674837cea1b58f88b5352543ca27b&amp;quot;,&amp;quot;chainId&amp;quot;:&amp;quot;0x1&amp;quot;,&amp;quot;transactionIndex&amp;quot;:&amp;quot;0x39&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;0x2&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;accessList&amp;quot;:[],&amp;quot;blockNumber&amp;quot;:&amp;quot;0x10b2027&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0x55702f5d14736fc9d0c58fdac2d2052a602db171c46b5e1fa9ff6af5c277f9a2&amp;quot;,&amp;quot;maxFeePerGas&amp;quot;:&amp;quot;0x48a413364&amp;quot;,&amp;quot;maxPriorityFeePerGas&amp;quot;:&amp;quot;0x5f5e100&amp;quot;,&amp;quot;r&amp;quot;:&amp;quot;0x5a703d389d23b51adf8ef0f55db8876e7392636797b68a4be6afe73e76d7e1f2&amp;quot;,&amp;quot;s&amp;quot;:&amp;quot;0x4b4bb11257c4434a0acc2672357f8793476e4bfdf98bc30d2389ce335e7de64e&amp;quot;,&amp;quot;v&amp;quot;:&amp;quot;0x1&amp;quot;}&lt;br /&gt;2023-06-18 19:23:05		Info	{&amp;quot;gas&amp;quot;:&amp;quot;0x186a0&amp;quot;,&amp;quot;nonce&amp;quot;:&amp;quot;0x46533&amp;quot;,&amp;quot;r&amp;quot;:&amp;quot;0xfeea052a4ac2283ca058a657a806ba0916d8e7d52d2a577f150c40eb1dfbec65&amp;quot;,&amp;quot;s&amp;quot;:&amp;quot;0x5bf0089a3c060ba787b67a205b44e1065a0d11d132b41737ab9adf0f55066811&amp;quot;,&amp;quot;transactionIndex&amp;quot;:&amp;quot;0x38&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;0x78f0975742c400&amp;quot;,&amp;quot;blockHash&amp;quot;:&amp;quot;0xf833ed36435c53d63bd7109bb1e85383075534410c14573881bf26d912f46a89&amp;quot;,&amp;quot;chainId&amp;quot;:&amp;quot;0x1&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0x56bdf1b38e23db66e8d1c4014d1e9f690a9217d8a0232489210325fc69e25cf9&amp;quot;,&amp;quot;v&amp;quot;:&amp;quot;0x25&amp;quot;,&amp;quot;input&amp;quot;:&amp;quot;0x&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;blockNumber&amp;quot;:&amp;quot;0x10b2027&amp;quot;,&amp;quot;gasPrice&amp;quot;:&amp;quot;0x4a817c800&amp;quot;,&amp;quot;from&amp;quot;:&amp;quot;0x97b9d2102a9a65a26e1ee82d59e42d1b73b68689&amp;quot;,&amp;quot;to&amp;quot;:&amp;quot;0xcb513e99c020e9d15a6eafef873fef5d9f078221&amp;quot;}&lt;br /&gt;...&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Extract one piece of the data:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;{&lt;br /&gt;	&amp;quot;blockNumber&amp;quot;: &amp;quot;0x10b2027&amp;quot;,&lt;br /&gt;	&amp;quot;type&amp;quot;: &amp;quot;0x2&amp;quot;,&lt;br /&gt;	&amp;quot;accessList&amp;quot;: [],&lt;br /&gt;	&amp;quot;blockHash&amp;quot;: &amp;quot;0xf833ed36435c53d63bd7109bb1e85383075534410c14573881bf26d912f46a89&amp;quot;,&lt;br /&gt;	&amp;quot;from&amp;quot;: &amp;quot;0xd50521974d62f1fa34b8e81cb742ccf6147d05ff&amp;quot;,&lt;br /&gt;	&amp;quot;gasPrice&amp;quot;: &amp;quot;0x32ea2db37&amp;quot;,&lt;br /&gt;	&amp;quot;hash&amp;quot;: &amp;quot;0xf8f10f8f473c340b021298feb48d0affe529e8737a309c4cc1902e8989ef0914&amp;quot;,&lt;br /&gt;	&amp;quot;input&amp;quot;: &amp;quot;0xa22cb4650000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000000000000000000000000000000000000000000000000000000000000001&amp;quot;,&lt;br /&gt;	&amp;quot;v&amp;quot;: &amp;quot;0x0&amp;quot;,&lt;br /&gt;	&amp;quot;value&amp;quot;: &amp;quot;0x0&amp;quot;,&lt;br /&gt;	&amp;quot;maxFeePerGas&amp;quot;: &amp;quot;0x48a413364&amp;quot;,&lt;br /&gt;	&amp;quot;maxPriorityFeePerGas&amp;quot;: &amp;quot;0x5f5e100&amp;quot;,&lt;br /&gt;	&amp;quot;nonce&amp;quot;: &amp;quot;0x8&amp;quot;,&lt;br /&gt;	&amp;quot;r&amp;quot;: &amp;quot;0x8c1cc36f43b02c9e9e454153588cc9d38757f1da69ec49d3cfdda74ab69e06a8&amp;quot;,&lt;br /&gt;	&amp;quot;s&amp;quot;: &amp;quot;0x2f3dd3e5ddf9e5d42c128a8e900026aca7568fa83c68cf332e1328066ee8d03a&amp;quot;,&lt;br /&gt;	&amp;quot;transactionIndex&amp;quot;: &amp;quot;0x3a&amp;quot;,&lt;br /&gt;	&amp;quot;chainId&amp;quot;: &amp;quot;0x1&amp;quot;,&lt;br /&gt;	&amp;quot;gas&amp;quot;: &amp;quot;0x1142d&amp;quot;,&lt;br /&gt;	&amp;quot;to&amp;quot;: &amp;quot;0x8c3c0274c33f263f0a55d129cfc8eaa3667a9e8b&amp;quot;&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;### Listening with the WebSocket protocol&lt;br /&gt;&lt;br /&gt;In the FMZ Quant Trading Platform, we use the ```Dial``` function to create ```WebSocket``` connections, you can check the ```FMZ API``` documentation to learn the ```Dial``` function.&lt;br /&gt;&lt;br /&gt;The test code in this section runs in the Ethereum mainnet environment, and it is easier to use the FMZ Quant to test in live trading due to the use of WebSocket protocol communication. The Websocket protocol subscription messages are:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;{&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;id&amp;quot;: 1, &amp;quot;method&amp;quot;: &amp;quot;eth_subscribe&amp;quot;, &amp;quot;params&amp;quot;: [&amp;quot;newPendingTransactions&amp;quot;]}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;In addition to ```newPendingTransactions```, you can also subscribe to ```newHeads```, ```logs```.&lt;br /&gt;&lt;br /&gt;Receiving data pushed by ```WebSocket``` connections:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;{&lt;br /&gt;	&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;,&lt;br /&gt;	&amp;quot;method&amp;quot;: &amp;quot;eth_subscription&amp;quot;,&lt;br /&gt;	&amp;quot;params&amp;quot;: {&lt;br /&gt;		&amp;quot;subscription&amp;quot;: &amp;quot;0x2c5c087b4aa188e008f4747828ef4e61&amp;quot;,&lt;br /&gt;		&amp;quot;result&amp;quot;: &amp;quot;0x69c4251cecb814e17cfe7a5ee41742a616f9a4d1bbf245c49b186b1006fd14d3&amp;quot;&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Then further query ```transaction``` according to which: ```&amp;quot;result&amp;quot;: &amp;quot;0x69c4251cecb814e17cfe7a5ee41742a616f9a4d1bbf245c49b186b1006fd14d3&amp;quot;```. For a specific ```transaction```, we use the Ethereum RPC method ```eth_getTransactionByHash``` to query.&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;var ws = null &lt;br /&gt;&lt;br /&gt;function main () {    &lt;br /&gt;    // {&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;id&amp;quot;: 1, &amp;quot;method&amp;quot;: &amp;quot;eth_subscribe&amp;quot;, &amp;quot;params&amp;quot;: [&amp;quot;xxxxx&amp;quot;]}  , &amp;quot;xxxxx&amp;quot; is the specific message to subscribe to&lt;br /&gt;    var payload = {&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;id&amp;quot;: 1, &amp;quot;method&amp;quot;: &amp;quot;eth_subscribe&amp;quot;, &amp;quot;params&amp;quot;: [&amp;quot;newPendingTransactions&amp;quot;]}&lt;br /&gt;    &lt;br /&gt;    // wss://mainnet.infura.io/ws/v3/xxxxx , &amp;quot;xxxxx&amp;quot; is your infura key&lt;br /&gt;    var infuraKey = &amp;quot;your key&amp;quot;&lt;br /&gt;&lt;br /&gt;    ws = Dial(&amp;quot;wss://mainnet.infura.io/ws/v3/&amp;quot; + infuraKey + &amp;quot;|reconnect=true&amp;amp;payload=&amp;quot; + JSON.stringify(payload))&lt;br /&gt;    if (!ws) {&lt;br /&gt;        throw &amp;quot;websocket link infura failed!&amp;quot;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // eth_getTransactionByHash call count&lt;br /&gt;    var getTransactionCounter = 0&lt;br /&gt;&lt;br /&gt;    var beginTS = new Date().getTime()&lt;br /&gt;&lt;br /&gt;    // Loop to get messages&lt;br /&gt;    while (true) {&lt;br /&gt;        // Receive push messages&lt;br /&gt;        var data = ws.read()&lt;br /&gt;        if (data) {&lt;br /&gt;            var ts = new Date().getTime()&lt;br /&gt;&lt;br /&gt;            if (ts - beginTS &amp;gt;= 1000) {&lt;br /&gt;                getTransactionCounter = 0&lt;br /&gt;                beginTS = ts &lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // Check transaction details based on txHash&lt;br /&gt;            if (ts - beginTS &amp;lt; 1000 &amp;amp;&amp;amp; getTransactionCounter &amp;gt;= 100) {&lt;br /&gt;                Sleep(1000)&lt;br /&gt;                getTransactionCounter = 0&lt;br /&gt;                beginTS = ts &lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            var obj = JSON.parse(data)&lt;br /&gt;            if (obj[&amp;quot;params&amp;quot;] &amp;amp;&amp;amp; obj[&amp;quot;params&amp;quot;][&amp;quot;result&amp;quot;]) {&lt;br /&gt;                var transcationInfo = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getTransactionByHash&amp;quot;, obj[&amp;quot;params&amp;quot;][&amp;quot;result&amp;quot;])&lt;br /&gt;                Log(obj[&amp;quot;params&amp;quot;][&amp;quot;result&amp;quot;], &amp;quot;transcationInfo:&amp;quot;, transcationInfo)&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            getTransactionCounter++&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        LogStatus(_D())&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onexit() {&lt;br /&gt;    Log(&amp;quot;Disconnect WS connection&amp;quot;)&lt;br /&gt;    ws.close()&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Create a live trading to run the above code, you can receive the data pushed by the WebSocket connection, the data is pushed constantly, we extract one of them - ```transaction```:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;{&lt;br /&gt;	&amp;quot;maxPriorityFeePerGas&amp;quot;: &amp;quot;0x5f5e100&amp;quot;,&lt;br /&gt;	&amp;quot;nonce&amp;quot;: &amp;quot;0x1a9&amp;quot;,&lt;br /&gt;	&amp;quot;accessList&amp;quot;: [],&lt;br /&gt;	&amp;quot;blockNumber&amp;quot;: &amp;quot;0x10b1c9f&amp;quot;,&lt;br /&gt;	&amp;quot;from&amp;quot;: &amp;quot;0x5888700be02f52c8adf85890886ef84a6b8a7829&amp;quot;,&lt;br /&gt;	&amp;quot;blockHash&amp;quot;: &amp;quot;0x92c3d77ea218cdc0967ab74b6005bb393b92355047f206c7e2d59d41828e7fa9&amp;quot;,&lt;br /&gt;	&amp;quot;chainId&amp;quot;: &amp;quot;0x1&amp;quot;,&lt;br /&gt;	&amp;quot;gasPrice&amp;quot;: &amp;quot;0x34fdbf43d&amp;quot;,&lt;br /&gt;	&amp;quot;s&amp;quot;: &amp;quot;0x7d86ae29a786a61b9e74a7a9e2cc4b39b7913aa3d4c3816ccb07528fed82048a&amp;quot;,&lt;br /&gt;	&amp;quot;to&amp;quot;: &amp;quot;0xfc2068c3d47b575a60f6a4a7bf60dea0ac368e01&amp;quot;,&lt;br /&gt;	&amp;quot;type&amp;quot;: &amp;quot;0x2&amp;quot;,&lt;br /&gt;	&amp;quot;v&amp;quot;: &amp;quot;0x1&amp;quot;,&lt;br /&gt;	&amp;quot;value&amp;quot;: &amp;quot;0x0&amp;quot;,&lt;br /&gt;	&amp;quot;gas&amp;quot;: &amp;quot;0x1aad3&amp;quot;,&lt;br /&gt;	&amp;quot;hash&amp;quot;: &amp;quot;0x2c77c0704aefbb26db460cbb71efdb488df968ad53d2c2b3f1e1172056b40b22&amp;quot;,&lt;br /&gt;	&amp;quot;input&amp;quot;: &amp;quot;0x42842e0e0000000000000000000000005888700be02f52c8adf85890886ef84a6b8a7829000000000000000000000000d2d07e4d1bb0f40ac3e4aa7cc3ad05d348bfd2c3000000000000000000000000000000000000000000000000000000000000180b&amp;quot;,&lt;br /&gt;	&amp;quot;maxFeePerGas&amp;quot;: &amp;quot;0x4712d1273&amp;quot;,&lt;br /&gt;	&amp;quot;r&amp;quot;: &amp;quot;0x8ec58f95f6d9729a6eee075e6976658b6c5346cbc90eb68ac361a40af073b10e&amp;quot;,&lt;br /&gt;	&amp;quot;transactionIndex&amp;quot;: &amp;quot;0xc1&amp;quot;&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Excerpted (partial omission) log data:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-18 16:20:07		Info	Disconnect WS connection&lt;br /&gt;2023-06-18 16:20:07		Info	0xba07ca903f9eafbfa7d494bb26197713034b9ca2dd3c19bc0898af3f35b59343 transcationInfo: {&amp;quot;accessList&amp;quot;:[],&amp;quot;from&amp;quot;:&amp;quot;0xe2977d60182da068dfd78693f96362ee7a2e9644&amp;quot;,&amp;quot;nonce&amp;quot;:&amp;quot;0xf&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;blockHash&amp;quot;:&amp;quot;0x92c3d77ea218cdc0967ab74b6005bb393b92355047f206c7e2d59d41828e7fa9&amp;quot;,&amp;quot;blockNumber&amp;quot;:&amp;quot;0x10b1c9f&amp;quot;,&amp;quot;chainId&amp;quot;:&amp;quot;0x1&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0xba07ca903f9eafbfa7d494bb26197713034b9ca2dd3c19bc0898af3f35b59343&amp;quot;,&amp;quot;maxFeePerGas&amp;quot;:&amp;quot;0x530c30b70&amp;quot;,&amp;quot;r&amp;quot;:&amp;quot;0xf28bfdf372a5401a2e00675c6ebe8d5e73f2c955db44b1aa56240b9197d6cbc7&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;0x2&amp;quot;,&amp;quot;v&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;gas&amp;quot;:&amp;quot;0x21079&amp;quot;,&amp;quot;gasPrice&amp;quot;:&amp;quot;0x367b3783d&amp;quot;,&amp;quot;input&amp;quot;:&amp;quot;0x657bb1130000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001e0300000000000000000000000033c6eec1723b12c46732f7ab41398de45641fa42000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041976bd7d021a5b94cbba72b291093b50a0ecf21d1c6cd8193fbfcd685c4723ce068feb249bdcace58c28eb3b6cc647e8c839b0826c84f8dfe4c31d57d1ac1f0111b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000648ebef50000000000000000000000000000000000000000000000000000000000000000&amp;quot;,&amp;quot;maxPriorityFeePerGas&amp;quot;:&amp;quot;0x1dcd6500&amp;quot;,&amp;quot;s&amp;quot;:&amp;quot;0x71d51246bb60e792f963a3c75c46fd8f557921ce6face7224c944e1768a76ca&amp;quot;,&amp;quot;to&amp;quot;:&amp;quot;0x0b51eb9d0e54c562fedc07ceba453f05b70c4b79&amp;quot;,&amp;quot;transactionIndex&amp;quot;:&amp;quot;0x40&amp;quot;}&lt;br /&gt;2023-06-18 16:20:07		Info	0x2c77c0704aefbb26db460cbb71efdb488df968ad53d2c2b3f1e1172056b40b22 transcationInfo: {&amp;quot;maxPriorityFeePerGas&amp;quot;:&amp;quot;0x5f5e100&amp;quot;,&amp;quot;nonce&amp;quot;:&amp;quot;0x1a9&amp;quot;,&amp;quot;accessList&amp;quot;:[],&amp;quot;blockNumber&amp;quot;:&amp;quot;0x10b1c9f&amp;quot;,&amp;quot;from&amp;quot;:&amp;quot;0x5888700be02f52c8adf85890886ef84a6b8a7829&amp;quot;,&amp;quot;blockHash&amp;quot;:&amp;quot;0x92c3d77ea218cdc0967ab74b6005bb393b92355047f206c7e2d59d41828e7fa9&amp;quot;,&amp;quot;chainId&amp;quot;:&amp;quot;0x1&amp;quot;,&amp;quot;gasPrice&amp;quot;:&amp;quot;0x34fdbf43d&amp;quot;,&amp;quot;s&amp;quot;:&amp;quot;0x7d86ae29a786a61b9e74a7a9e2cc4b39b7913aa3d4c3816ccb07528fed82048a&amp;quot;,&amp;quot;to&amp;quot;:&amp;quot;0xfc2068c3d47b575a60f6a4a7bf60dea0ac368e01&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;0x2&amp;quot;,&amp;quot;v&amp;quot;:&amp;quot;0x1&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;gas&amp;quot;:&amp;quot;0x1aad3&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0x2c77c0704aefbb26db460cbb71efdb488df968ad53d2c2b3f1e1172056b40b22&amp;quot;,&amp;quot;input&amp;quot;:&amp;quot;0x42842e0e0000000000000000000000005888700be02f52c8adf85890886ef84a6b8a7829000000000000000000000000d2d07e4d1bb0f40ac3e4aa7cc3ad05d348bfd2c3000000000000000000000000000000000000000000000000000000000000180b&amp;quot;,&amp;quot;maxFeePerGas&amp;quot;:&amp;quot;0x4712d1273&amp;quot;,&amp;quot;r&amp;quot;:&amp;quot;0x8ec58f95f6d9729a6eee075e6976658b6c5346cbc90eb68ac361a40af073b10e&amp;quot;,&amp;quot;transactionIndex&amp;quot;:&amp;quot;0xc1&amp;quot;}&lt;br /&gt;2023-06-18 16:20:07		Info	0xbc42d5db10e5cb2e888c76005c522cb2474a0c0a7325feb867b618f69ff26f2a transcationInfo: {&amp;quot;accessList&amp;quot;:[],&amp;quot;blockNumber&amp;quot;:&amp;quot;0x10b1c9f&amp;quot;,&amp;quot;gas&amp;quot;:&amp;quot;0x1cc12b&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0xbc42d5db10e5cb2e888c76005c522cb2474a0c0a7325feb867b618f69ff26f2a&amp;quot;,&amp;quot;maxFeePerGas&amp;quot;:&amp;quot;0x6ab262e5c&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;v&amp;quot;:&amp;quot;0x1&amp;quot;,&amp;quot;chainId&amp;quot;:&amp;quot;0x1&amp;quot;,&amp;quot;from&amp;quot;:&amp;quot;0xc1b634853cb333d3ad8663715b08f41a3aec47cc&amp;quot;,&amp;quot;input&amp;quot;:&amp;quot;0x8f111f3c000000000000000000000000000000000000000000000000000000000003b83700000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000e0fa2000000000000000000000000e64a54e2533fd126c2e452c5fab544d80e2e4eb50000000000000000000000000000000000000000000000000000000004c6ff1c0000000000000000000000000000000000000000000000000000000004c70029000000000000000000000000000000000000000000000000000000000001822d005b1979341221e80ed20b20d832de88a8a4b535fe9990a90c165f3c95ad085ab9445c0a998c70edff76f1c2de3f4263d7e4fe3c3fb73fe7dcfbdede92371842fb883267f5408c8aaf08ba2f6c22463f19da98183d2302735615460d7380d6f9ff5e764e75bcaca9a93946cf644cd4d4448f314c4cf60cd0353f085aa0562d70e16a510b8bc4c2a09b5e7fafcd43f07dc1b5dd1782962af8f6fff7a6965bfc127e11501a72c64913d58e624333f9ec51687c7cb1bb4a9850541f1e03b2790ed4ee508052910dfe22542d900548d5243ca238811427491d49e98cf269ccab5b1724f0f9698120e406c00910c4090c0e84e0400e2706822d2a001a3964a0ca8101700a547342c2c1fff8934a988416f020a0c98f0909c7f529875f8443914e10b58145c79d38914d1fafbc9ee57ebcb377e4ac1cd252bdebe3c59e8e917fea7dbc7bf66dfc1846482a858645b95555b3ecc9ab4f9e2b0e3e78d68379b009e606a1cefe675670a5eabd5f5a2efa5d77a1084288480c98d01c70a3d8c6b854496e2a966dc9051b13b872b7c6c2c5d82676fd8e82c680514333db21db2006d23f42074021de7e61c54d88b01824d40f03d1505eb6ec6d0cb7ccd38deb821517a5e63d0e89f6bf0385f109c81ea36dd00e7a903a100290f5b47a940ed146ae9338ff8bc17a2b5bc457614d0831e743e485c0de84636b034400bf6bd192ff723045cc170e109aabf273dc9de19c9987038515b6613249f471f9ddeb31331cc1643902212d20241c417532ad7e4a9ac742b4b5f68e1019795cf9386dcf36037502c13ff51f50a2202b2c1cac1c0b38a21ec798deff778c9a6b679d16d0521d2df89c439f4f8f9425ed378f4194d03d00&lt;br /&gt;2023-06-18 16:20:06		Info	0xff0945c3d682a37e18ee433d56c8bedbb93d9ac368af968ed8d53b655575e8e5 transcationInfo: {&amp;quot;gas&amp;quot;:&amp;quot;0x5208&amp;quot;,&amp;quot;s&amp;quot;:&amp;quot;0x63572e1fa060841b939cea0849154e55781fe0efcbdfe5ce6979b44ce0980e4a&amp;quot;,&amp;quot;transactionIndex&amp;quot;:&amp;quot;0xa7&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;0x113e9d515e400&amp;quot;,&amp;quot;blockHash&amp;quot;:&amp;quot;0x92c3d77ea218cdc0967ab74b6005bb393b92355047f206c7e2d59d41828e7fa9&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0xff0945c3d682a37e18ee433d56c8bedbb93d9ac368af968ed8d53b655575e8e5&amp;quot;,&amp;quot;nonce&amp;quot;:&amp;quot;0x2&amp;quot;,&amp;quot;r&amp;quot;:&amp;quot;0x698fe26331ad39ba89c4d30985b707792ea4ab09b25205727f8fac2a6120b54a&amp;quot;,&amp;quot;gasPrice&amp;quot;:&amp;quot;0x35458af00&amp;quot;,&amp;quot;from&amp;quot;:&amp;quot;0x228d93af92d03184c07aa9e39b3d2d61b666686d&amp;quot;,&amp;quot;input&amp;quot;:&amp;quot;0x&amp;quot;,&amp;quot;to&amp;quot;:&amp;quot;0x0246177b98a5e42835cdcfaac1c274d3e6c39486&amp;quot;,&amp;quot;v&amp;quot;:&amp;quot;0x26&amp;quot;,&amp;quot;blockNumber&amp;quot;:&amp;quot;0x10b1c9f&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;0x0&amp;quot;,&amp;quot;chainId&amp;quot;:&amp;quot;0x1&amp;quot;}&lt;br /&gt;...&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;## Decoding Transaction Details&lt;br /&gt;&lt;br /&gt;In the previous course, we wrote a monitoring program to monitor pending transactions on Ethereum, get the pushed transaction hash via WebSocket protocol, and then query the specific transaction details based on the transaction hash.&lt;br /&gt;&lt;br /&gt;Next we want to do further parsing of the ```input``` field data in the transaction details data. The ```input``` field data looks like a jumble of hexadecimal data, but it actually encodes the content of the transaction: including the functions called, and the parameters entered, etc.&lt;br /&gt;&lt;br /&gt;After repeated and extensive testing, we found that the timeliness and quantity of data pushed over by the WebSocket connection has a lot to do with the RPC node currently in use, and the pushed data received by two different RPC node services (e.g., infura, ALCHEMY) when creating a WebSocket connection at the same time is not exactly the same, and since the current scenario generates a large number of requests, we still need to use a more stable and faster RPC service. The WebSocket connection also pushes a lot of transaction hashes that have been Pending for a long time, and when using ```eth_getTransactionByHash``` to query, you often get a null value (tested on FMZ, node.js).&lt;br /&gt;&lt;br /&gt;We use the ```alchemy``` RPC node this time: ```wss://eth-mainnet.g.alchemy.com/v2/oKmOQKbneVkxgHZfibs-iFhIlIAl6HDN```. The node supports both WebSocket and REST protocols.&lt;br /&gt;&lt;br /&gt;We monitor the ```multicall(uint256,bytes[])``` method of the router smart contract of the Uniswap decentralized exchange, so we need to calculate the function signature hash of the method first.&lt;br /&gt;&lt;br /&gt;```&lt;br /&gt;// Take the first 8 characters of the complete hash&lt;br /&gt;// multicall: 0x5ae401dc&lt;br /&gt;var sigHash = &amp;quot;0x&amp;quot; + Encode(&amp;quot;keccak256&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;hex&amp;quot;, &amp;quot;multicall(uint256,bytes[])&amp;quot;).slice(0, 8)&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Based on the example in the previous lesson, we have made some modifications. When receiving messages pushed by the WebSocket connection, the latest data is received using ```var data = ws.read(-2)``` method, and the ```read()``` function parameter is set to -2 to indicate that the latest data is returned immediately. We only care about the ```Transaction``` that contains the ```multicall``` call, using ```if (tx &amp;amp;&amp;amp; tx.input.indexOf(sigHash) ! == -1)``` to determine the filter.&lt;br /&gt;&lt;br /&gt;2 custom functions need to be designed:&lt;br /&gt;&lt;br /&gt;- ```calcAllFuncSigHash()```: Calculate signature hash for all methods based on ABI.&lt;br /&gt;- ```decodeCall()```: Decoding function.&lt;br /&gt;&lt;br /&gt;Next, when the ```multicall``` call is detected, the decoding operation can start, and the parameters of the ```multicall``` method are decoded for the first time: ```deadline``` and ```data```. ```deadline``` is a timestamp that is better understood, and ```data``` is another encoded ```calldata```, so you still need to continue to use the ```decodeCall()``` function to decode it.&lt;br /&gt;&lt;br /&gt;Example of a complete implementation:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;var ws = null &lt;br /&gt;var arrLog = []&lt;br /&gt;&lt;br /&gt;const ABI_Route = &amp;#39;[{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;_factoryV2&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;factoryV3&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;_positionManager&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;_WETH9&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;constructor&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;WETH9&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approveMax&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approveMaxMinusOne&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approveZeroThenMax&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;approveZeroThenMaxMinusOne&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;callPositionManager&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;result&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;paths&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint128[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amounts&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint128[]&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;maximumTickDivergence&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;secondsAgo&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;checkOracleSlippage&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;maximumTickDivergence&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;secondsAgo&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;checkOracleSlippage&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOutMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IV3SwapRouter.ExactInputParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;exactInput&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;fee&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOutMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint160&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;sqrtPriceLimitX96&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint160&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IV3SwapRouter.ExactInputSingleParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;exactInputSingle&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountInMaximum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IV3SwapRouter.ExactOutputParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;exactOutput&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;fee&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountInMaximum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint160&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;sqrtPriceLimitX96&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint160&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IV3SwapRouter.ExactOutputSingleParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;exactOutputSingle&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;factory&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;factoryV2&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;getApprovalType&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;enum IApproveAndCall.ApprovalType&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token0&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token1&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tokenId&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount0Min&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount1Min&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IApproveAndCall.IncreaseLiquidityParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;increaseLiquidity&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;result&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;components&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token0&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token1&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;fee&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;int24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tickLower&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;int24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;int24&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;tickUpper&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;int24&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount0Min&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount1Min&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;internalType&amp;quot;:&amp;quot;struct IApproveAndCall.MintParams&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;params&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;tuple&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;mint&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;result&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;previousBlockhash&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;multicall&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;deadline&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;multicall&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;multicall&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;bytes[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;results&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes[]&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;positionManager&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;view&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;pull&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[],&amp;quot;name&amp;quot;:&amp;quot;refundETH&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;deadline&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint8&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;selfPermit&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;nonce&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;expiry&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint8&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;selfPermitAllowed&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;nonce&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;expiry&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint8&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;selfPermitAllowedIfNecessary&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;deadline&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint8&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint8&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes32&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes32&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;selfPermitIfNecessary&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOutMin&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address[]&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;to&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;swapExactTokensForTokens&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountOut&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountInMax&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address[]&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;path&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address[]&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;to&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;swapTokensForExactTokens&amp;quot;,&amp;quot;outputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountIn&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;sweepToken&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;sweepToken&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeBips&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeRecipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;sweepTokenWithFee&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;token&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeBips&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeRecipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;sweepTokenWithFee&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;int256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount0Delta&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;int256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;int256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amount1Delta&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;int256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;bytes&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;_data&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;bytes&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;uniswapV3SwapCallback&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;nonpayable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;unwrapWETH9&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;unwrapWETH9&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;recipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeBips&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeRecipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;unwrapWETH9WithFee&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;amountMinimum&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeBips&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;},{&amp;quot;internalType&amp;quot;:&amp;quot;address&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;feeRecipient&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;address&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;unwrapWETH9WithFee&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;inputs&amp;quot;:[{&amp;quot;internalType&amp;quot;:&amp;quot;uint256&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;uint256&amp;quot;}],&amp;quot;name&amp;quot;:&amp;quot;wrapETH&amp;quot;,&amp;quot;outputs&amp;quot;:[],&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;function&amp;quot;},{&amp;quot;stateMutability&amp;quot;:&amp;quot;payable&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;receive&amp;quot;}]&amp;#39;&lt;br /&gt;&lt;br /&gt;function calcAllFuncSigHash(jsonABI) {&lt;br /&gt;    var mapSigHash = {}&lt;br /&gt;    for (var i in jsonABI) {&lt;br /&gt;        var ele = jsonABI[i]&lt;br /&gt;        if (typeof(ele[&amp;quot;name&amp;quot;]) != &amp;quot;undefined&amp;quot;) {&lt;br /&gt;            if (ele[&amp;quot;inputs&amp;quot;]) {&lt;br /&gt;                var funcName = ele[&amp;quot;name&amp;quot;]&lt;br /&gt;                if (ele[&amp;quot;inputs&amp;quot;].length == 0) {&lt;br /&gt;                    var methodId = &amp;quot;0x&amp;quot; + Encode(&amp;quot;keccak256&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;hex&amp;quot;, funcName + &amp;quot;()&amp;quot;).slice(0, 8)&lt;br /&gt;                    mapSigHash[methodId] = {&amp;quot;argsTypeList&amp;quot;: [], &amp;quot;argsNameList&amp;quot;: [], &amp;quot;funcName&amp;quot;: funcName}&lt;br /&gt;                } else {&lt;br /&gt;                    var arr = []&lt;br /&gt;                    var arrName = []&lt;br /&gt;                    var argPrototype = []&lt;br /&gt;                    for (var j in ele[&amp;quot;inputs&amp;quot;]) {&lt;br /&gt;                        var inputType = ele[&amp;quot;inputs&amp;quot;][j][&amp;quot;type&amp;quot;]&lt;br /&gt;                        if (inputType == &amp;quot;tuple&amp;quot;) {                            &lt;br /&gt;                            var components = ele[&amp;quot;inputs&amp;quot;][j][&amp;quot;components&amp;quot;]&lt;br /&gt;                            var tupleType = []&lt;br /&gt;                            var protoType = []&lt;br /&gt;                            for (var componentsIdx = 0; componentsIdx &amp;lt; components.length; componentsIdx++) {&lt;br /&gt;                                tupleType.push(components[componentsIdx][&amp;quot;type&amp;quot;])&lt;br /&gt;                                protoType.push(components[componentsIdx][&amp;quot;name&amp;quot;] + &amp;quot; &amp;quot; + components[componentsIdx][&amp;quot;type&amp;quot;])&lt;br /&gt;                            }&lt;br /&gt;                            arr.push(&amp;quot;(&amp;quot; + tupleType.join() + &amp;quot;)&amp;quot;)&lt;br /&gt;                            arrName.push(ele[&amp;quot;inputs&amp;quot;][j][&amp;quot;name&amp;quot;])&lt;br /&gt;                            // Prototype&lt;br /&gt;                            argPrototype.push(&amp;quot;tuple&amp;quot; + &amp;quot;(&amp;quot; + protoType.join() + &amp;quot;)&amp;quot;)&lt;br /&gt;                        } else {&lt;br /&gt;                            arr.push(inputType)&lt;br /&gt;                            arrName.push(ele[&amp;quot;inputs&amp;quot;][j][&amp;quot;name&amp;quot;])&lt;br /&gt;                            // Prototype&lt;br /&gt;                            argPrototype.push(inputType)&lt;br /&gt;                        }                        &lt;br /&gt;                    }&lt;br /&gt;                    var functionSignature = funcName + &amp;quot;(&amp;quot; + arr.join() + &amp;quot;)&amp;quot;&lt;br /&gt;                    var methodId = &amp;quot;0x&amp;quot; + Encode(&amp;quot;keccak256&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;hex&amp;quot;, functionSignature).slice(0, 8)&lt;br /&gt;                    mapSigHash[methodId] = {&amp;quot;argsTypeList&amp;quot;: arr, &amp;quot;argsNameList&amp;quot;: arrName, &amp;quot;funcName&amp;quot;: funcName, &amp;quot;argPrototype&amp;quot;: argPrototype}&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    return mapSigHash&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function decodeCall(input, abi) {&lt;br /&gt;    var mapSigHash = calcAllFuncSigHash(JSON.parse(abi))&lt;br /&gt;    var methodId = input.slice(0, 10)&lt;br /&gt;    var data = input.slice(10)&lt;br /&gt;    &lt;br /&gt;    var decodedArgs = {}&lt;br /&gt;    var infoMethod = mapSigHash[methodId]&lt;br /&gt;    if (typeof(infoMethod) == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;        return [methodId, mapSigHash]&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    var arr = []&lt;br /&gt;    for (var i = 0; i &amp;lt; infoMethod[&amp;quot;argsTypeList&amp;quot;].length; i++) {&lt;br /&gt;        if (infoMethod[&amp;quot;argsTypeList&amp;quot;][i].startsWith(&amp;quot;(&amp;quot;)) {&lt;br /&gt;            arr.push(infoMethod[&amp;quot;argPrototype&amp;quot;][i])&lt;br /&gt;        } else {&lt;br /&gt;            arr.push(infoMethod[&amp;quot;argsTypeList&amp;quot;][i])&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    if (arr.length == 0) {&lt;br /&gt;        return {&amp;quot;funcName&amp;quot;: infoMethod[&amp;quot;funcName&amp;quot;], &amp;quot;args&amp;quot;: decodedArgs}&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    var args = exchange.IO(&amp;quot;decode&amp;quot;, arr.join(), data)&lt;br /&gt;&lt;br /&gt;    if (!Array.isArray(args)) {&lt;br /&gt;        args = [args]&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (args.length != infoMethod[&amp;quot;argsNameList&amp;quot;].length) {&lt;br /&gt;        Log(&amp;quot;args:&amp;quot;, args)&lt;br /&gt;        Log(&amp;quot;infoMethod:&amp;quot;, infoMethod)&lt;br /&gt;        throw &amp;quot;The decoded args are not equal to the argsNameList&amp;quot;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    for (var i = 0; i &amp;lt; infoMethod[&amp;quot;argsNameList&amp;quot;].length; i++) {&lt;br /&gt;        var key = infoMethod[&amp;quot;argsNameList&amp;quot;][i]&lt;br /&gt;        var value = args[i]&lt;br /&gt;        decodedArgs[key] = value&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return {&amp;quot;funcName&amp;quot;: infoMethod[&amp;quot;funcName&amp;quot;], &amp;quot;args&amp;quot;: decodedArgs}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function main () {&lt;br /&gt;    // {&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;id&amp;quot;: 1, &amp;quot;method&amp;quot;: &amp;quot;eth_subscribe&amp;quot;, &amp;quot;params&amp;quot;: [&amp;quot;xxxxx&amp;quot;]}  , &amp;quot;xxxxx&amp;quot; is the specific message of the subscription&lt;br /&gt;    var payload = {&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;id&amp;quot;: 1, &amp;quot;method&amp;quot;: &amp;quot;eth_subscribe&amp;quot;, &amp;quot;params&amp;quot;: [&amp;quot;newPendingTransactions&amp;quot;]}&lt;br /&gt;    &lt;br /&gt;    // Use the alchemy service&lt;br /&gt;    ws = Dial(&amp;quot;wss://eth-mainnet.g.alchemy.com/v2/oKmOQKbneVkxgHZfibs-iFhIlIAl6HDN&amp;quot; + &amp;quot;|reconnect=true&amp;amp;payload=&amp;quot; + JSON.stringify(payload))&lt;br /&gt;    if (!ws) {&lt;br /&gt;        throw &amp;quot;websocket link to alchemy failed!&amp;quot;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // eth_getTransactionByHash call count&lt;br /&gt;    var getTransactionCounter = 0&lt;br /&gt;    &lt;br /&gt;    // Start Timestamp&lt;br /&gt;    var beginTS = new Date().getTime()&lt;br /&gt;    &lt;br /&gt;    // Calculate function signature hash&lt;br /&gt;    var sigHash = &amp;quot;0x&amp;quot; + Encode(&amp;quot;keccak256&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;hex&amp;quot;, &amp;quot;multicall(uint256,bytes[])&amp;quot;).slice(0, 8)&lt;br /&gt;    Log(&amp;quot;sigHash:&amp;quot;, sigHash)&lt;br /&gt;&lt;br /&gt;    // Loop for messages&lt;br /&gt;    while (true) {&lt;br /&gt;        var msg = &amp;quot;&amp;quot;&lt;br /&gt;        var recv = null&lt;br /&gt;        // Receive pushed messages, use the read parameter -2, and return the latest data immediately&lt;br /&gt;        var data = ws.read(-2)&lt;br /&gt;        if (data &amp;amp;&amp;amp; data != &amp;quot;&amp;quot;) {&lt;br /&gt;            var ts = new Date().getTime()&lt;br /&gt;&lt;br /&gt;            if (ts - beginTS &amp;gt;= 1000) {&lt;br /&gt;                getTransactionCounter = 0&lt;br /&gt;                beginTS = ts &lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // Check transaction details based on txHash&lt;br /&gt;            if (ts - beginTS &amp;lt; 1000 &amp;amp;&amp;amp; getTransactionCounter &amp;gt;= 100) {&lt;br /&gt;                Sleep(1000)&lt;br /&gt;                getTransactionCounter = 0&lt;br /&gt;                beginTS = ts &lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            var obj = JSON.parse(data)&lt;br /&gt;            if (obj[&amp;quot;params&amp;quot;] &amp;amp;&amp;amp; obj[&amp;quot;params&amp;quot;][&amp;quot;result&amp;quot;]) {&lt;br /&gt;                var txHash = obj[&amp;quot;params&amp;quot;][&amp;quot;result&amp;quot;]&lt;br /&gt;                var tx = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_getTransactionByHash&amp;quot;, txHash)&lt;br /&gt;                &lt;br /&gt;                if (tx &amp;amp;&amp;amp; tx.input.indexOf(sigHash) !== -1) {&lt;br /&gt;                    // Decode transaction details&lt;br /&gt;                    arrLog = []&lt;br /&gt;                    var decodedInput = decodeCall(tx.input, ABI_Route)&lt;br /&gt;&lt;br /&gt;                    // Log(&amp;quot;----------------&amp;quot;, txHash, &amp;quot;/&amp;quot;, decodedInput[&amp;quot;funcName&amp;quot;], &amp;quot;----------------&amp;quot;, &amp;quot;#FF0000&amp;quot;)&lt;br /&gt;                    arrLog.push(&amp;quot;----------------&amp;quot; + txHash + &amp;quot;/&amp;quot; + decodedInput[&amp;quot;funcName&amp;quot;] + &amp;quot;----------------&amp;quot; + &amp;quot;#FF0000&amp;quot;)&lt;br /&gt;                    arrLog.push(tx.from + &amp;quot; -&amp;gt; &amp;quot; + tx.to)&lt;br /&gt;&lt;br /&gt;                    for (var i = 0; i &amp;lt; decodedInput[&amp;quot;args&amp;quot;][&amp;quot;data&amp;quot;].length; i++) {&lt;br /&gt;                        var calldata = &amp;quot;0x&amp;quot; + decodedInput[&amp;quot;args&amp;quot;][&amp;quot;data&amp;quot;][i]&lt;br /&gt;                        var decodedCalldata = decodeCall(calldata, ABI_Route)&lt;br /&gt;&lt;br /&gt;                        // Log(&amp;quot;----------------&amp;quot;, decodedCalldata[&amp;quot;funcName&amp;quot;], &amp;quot;----------------&amp;quot;, &amp;quot;#FF0000&amp;quot;)&lt;br /&gt;                        arrLog.push(&amp;quot;----------------&amp;quot; + decodedCalldata[&amp;quot;funcName&amp;quot;] + &amp;quot;----------------&amp;quot; + &amp;quot;#FF0000&amp;quot;)&lt;br /&gt;&lt;br /&gt;                        for (var key in decodedCalldata[&amp;quot;args&amp;quot;]) {&lt;br /&gt;                            // Log(key, decodedCalldata[&amp;quot;args&amp;quot;][key])&lt;br /&gt;                            arrLog.push(key + &amp;quot;: &amp;quot; + JSON.stringify(decodedCalldata[&amp;quot;args&amp;quot;][key]))&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    // Output logs&lt;br /&gt;                    for (var logIdx = arrLog.length - 1; logIdx &amp;gt;= 0; logIdx--) {&lt;br /&gt;                        Log(arrLog[logIdx])&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                &lt;br /&gt;                getTransactionCounter++&lt;br /&gt;            }&lt;br /&gt;            recv = obj&lt;br /&gt;        } else if (data == null) {&lt;br /&gt;            msg = &amp;quot;The buffer queue is empty, time:&amp;quot; + _D()&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        LogStatus(_D(), &amp;quot;, msg:&amp;quot;, msg, &amp;quot;, recv:&amp;quot;, recv)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onexit() {&lt;br /&gt;    Log(&amp;quot;Disconnect WS connection&amp;quot;)&lt;br /&gt;    ws.close()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onerror() {&lt;br /&gt;    Log(&amp;quot;Disconnect WS connection&amp;quot;)&lt;br /&gt;    ws.close()&lt;br /&gt;&lt;br /&gt;    for (var logIdx = arrLog.length - 1; logIdx &amp;gt;= 0; logIdx--) {        &lt;br /&gt;        Log(arrLog[logIdx])&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Create a live trading to test:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-20 17:01:00		Info	----------------0x5288a7bd6e0f57162ca763df722de73793e542734d7d2b7af5755664e2e67910/multicall----------------&lt;br /&gt;2023-06-20 17:01:00		Info	0x851b594033d57c98af753bcb3a7d0237a615de32 -&amp;gt; 0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45&lt;br /&gt;2023-06-20 17:01:00		Info	----------------exactInputSingle----------------&lt;br /&gt;2023-06-20 17:01:00		Info	params: {&amp;quot;tokenOut&amp;quot;:&amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;,&amp;quot;fee&amp;quot;:&amp;quot;10000&amp;quot;,&amp;quot;recipient&amp;quot;:&amp;quot;0x0000000000000000000000000000000000000002&amp;quot;,&amp;quot;amountIn&amp;quot;:&amp;quot;8952087000296027130940868&amp;quot;,&amp;quot;amountOutMinimum&amp;quot;:&amp;quot;41638694112306829&amp;quot;,&amp;quot;sqrtPriceLimitX96&amp;quot;:&amp;quot;0&amp;quot;,&amp;quot;tokenIn&amp;quot;:&amp;quot;0xe1283567345349942acdfad3692924a1b16cf3cc&amp;quot;}&lt;br /&gt;2023-06-20 17:01:00		Info	----------------unwrapWETH9----------------&lt;br /&gt;2023-06-20 17:01:00		Info	amountMinimum: &amp;quot;41638694112306829&amp;quot;&lt;br /&gt;2023-06-20 17:01:00		Info	recipient: &amp;quot;0x851b594033d57c98af753bcb3a7d0237a615de32&amp;quot;&lt;br /&gt;2023-06-20 16:59:03		Info	----------------0x55e0c4a38a17d3aa6e8f558a66c77e9defa9f8f6e347536363ac1b921de9aaf3/multicall----------------&lt;br /&gt;2023-06-20 16:59:03		Info	0x27457ada2dd725c7d0f28e1737bdd0bf583c0f0b -&amp;gt; 0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45&lt;br /&gt;2023-06-20 16:59:03		Info	----------------swapExactTokensForTokens----------------&lt;br /&gt;2023-06-20 16:59:03		Info	amountIn: &amp;quot;816769666850161&amp;quot;&lt;br /&gt;2023-06-20 16:59:03		Info	amountOutMin: &amp;quot;40404501509302321&amp;quot;&lt;br /&gt;2023-06-20 16:59:03		Info	path: [&amp;quot;0x7863e06bca47ded821fcb53ab788eeb371243eda&amp;quot;,&amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;]&lt;br /&gt;2023-06-20 16:59:03		Info	to: &amp;quot;0x27457ada2dd725c7d0f28e1737bdd0bf583c0f0b&amp;quot;&lt;br /&gt;2023-06-20 16:58:25		Info	sigHash: 0x5ae401dc&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Screenshot:&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150279
" title="https://stocksharp.com/file/150279
"&gt;https://stocksharp.com/file/150279
&lt;/a&gt;&lt;br /&gt;You can see that the Transaction Hash is ```0x5288a7bd6e0f57162ca763df722de73793e542734d7d2b7af5755664e2e67910``` for this transaction, and the input data data contains the call to a ```multicall``` method call. This transaction is sent in the direction: 0x851b594033d57c98af753bcb3a7d0237a615de32 -&amp;gt; 0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45. ```0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45 ``` is Uniswap&amp;#39;s router contract address.&lt;br /&gt;&lt;a href="https://stocksharp.com/file/150280
" title="https://stocksharp.com/file/150280
"&gt;https://stocksharp.com/file/150280
&lt;/a&gt;&lt;br /&gt;The ```multicall``` package is parsed to call the contract&amp;#39;s ```exactInputSingle``` and ```unwrapWETH9``` methods and the specific parameters of these methods.&lt;br /&gt;&lt;br /&gt;```&lt;br /&gt;----------------exactInputSingle----------------&lt;br /&gt;params: {&lt;br /&gt;    &amp;quot;tokenOut&amp;quot;:&amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;,&lt;br /&gt;    &amp;quot;fee&amp;quot;:&amp;quot;10000&amp;quot;,&lt;br /&gt;    &amp;quot;recipient&amp;quot;:&amp;quot;0x0000000000000000000000000000000000000002&amp;quot;,&lt;br /&gt;    &amp;quot;amountIn&amp;quot;:&amp;quot;8952087000296027130940868&amp;quot;,&lt;br /&gt;    &amp;quot;amountOutMinimum&amp;quot;:&amp;quot;41638694112306829&amp;quot;,&lt;br /&gt;    &amp;quot;sqrtPriceLimitX96&amp;quot;:&amp;quot;0&amp;quot;,&lt;br /&gt;    &amp;quot;tokenIn&amp;quot;:&amp;quot;0xe1283567345349942acdfad3692924a1b16cf3cc&amp;quot;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;----------------unwrapWETH9----------------&lt;br /&gt;amountMinimum: &amp;quot;41638694112306829&amp;quot;&lt;br /&gt;recipient: &amp;quot;0x851b594033d57c98af753bcb3a7d0237a615de32&amp;quot;&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;If you are interested, you can modify and extend the example based on it to monitor more transactions and parse these on-chain operations.&lt;br /&gt;From: &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAAezbpL9G-wNBo0jpp0vfUOQlbPNxIPafGj0KHUDS3Y6ymnjI3ih-EYivoXMTwdB_xImkZVym3MGRgo05CPqrdGrc6JyRY60RJjFc3C_175fTPmWugUrzwB2XAHchNYfKaLj0DETRnzx1bxmPI86Fjo" title="https://blog.mathquant.com/2023/06/30/get-started-with-web3-development-easily-based-on-ethereum-using-fmz.html"&gt;https://blog.mathquant.c...-ethereum-using-fmz.html&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.com/topic/25691/</id>
    <title type="text">Get Started with web3 Development Easily Based on Ethereum Using FMZ (6)</title>
    <published>2024-04-16T03:28:35Z</published>
    <updated>2024-04-16T03:28:35Z</updated>
    <author>
      <name>FMZ</name>
      <uri>https://stocksharp.com/users/186354/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <category term="#trading" />
    <category term="#cryptocurrency" />
    <category term="#strategy" />
    <category term="#code" />
    <category term="#data" />
    <category term="#fmz" />
    <category term="#exchange" />
    <category term="#javascript" />
    <category term="#Ethereum" />
    <category term="#web3" />
    <content type="html">## Unit conversions&lt;br /&gt;&lt;br /&gt;Many of the calculations related to Ethereum have values that exceed the maximum safe integer of the ```JavaScript``` language. Therefore, some methods are needed on the FMZ Quant Trading Platform to handle large values, which we have used specifically in previous courses and have not covered in detail. This section will discuss this aspect in detail.&lt;br /&gt;&lt;br /&gt;Print the maximum safe integer defined in the ```JavaScript``` language:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    Log(&amp;quot;Number.MAX_SAFE_INTEGER:&amp;quot;, Number.MAX_SAFE_INTEGER)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Running results:&lt;br /&gt;&lt;br /&gt;&amp;gt; Number.MAX_SAFE_INTEGER: 9007199254740991&lt;br /&gt;&lt;br /&gt;### BigInt&lt;br /&gt;The smallest unit defined in Ethereum is ```1wei```, and the definition ```1Gwei``` is equal to ```1000000000 wei```. ```1Gwei``` is not really a very large number in Ethereum-related calculations, and some data is much larger than it. So these data with very large values can easily exceed ```Number.MAX_SAFE_INTEGER: 9007199254740991```.&lt;br /&gt;&lt;br /&gt;At FMZ Quant Trading Platform, we use the platform&amp;#39;s ```BigInt``` object to represent these very large integer data. Use the constructor ```BigInt()``` to construct the ```BigInt``` object. You can construct ```BigInt``` objects using numeric, hexadecimal numeric strings as parameters. Use the ```toString()``` method of ```BigInt``` object to output the data represented by the object as a string.&lt;br /&gt;&lt;br /&gt;The operations supported by the ```BigInt``` object are:&lt;br /&gt;&lt;br /&gt;- Addition: ```+```&lt;br /&gt;- Subtraction: ```-```&lt;br /&gt;- Multiplication: ```*```&lt;br /&gt;- Division: ```/```&lt;br /&gt;- Modulo operations: ```%```&lt;br /&gt;- Power operations: ```*```&lt;br /&gt;&lt;br /&gt;Refer to the following code examples:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    // Decimal representation of 1Gwei&lt;br /&gt;    var oneGwei = 1000000000&lt;br /&gt;&lt;br /&gt;    // Decimal to hexadecimal conversion of 1Gwei&lt;br /&gt;    var oneGweiForHex = &amp;quot;0x&amp;quot; + oneGwei.toString(16)&lt;br /&gt;&lt;br /&gt;    Log(&amp;quot;oneGwei : &amp;quot;, oneGwei)&lt;br /&gt;    Log(&amp;quot;oneGweiForHex : &amp;quot;, oneGweiForHex)&lt;br /&gt;&lt;br /&gt;    // Constructing BigInt objects&lt;br /&gt;    Log(&amp;quot;1Gwei / 1Gwei : &amp;quot;, (BigInt(oneGwei) / BigInt(oneGweiForHex)).toString(10))&lt;br /&gt;    Log(&amp;quot;1Gwei * 1Gwei : &amp;quot;, (BigInt(oneGwei) * BigInt(oneGweiForHex)).toString(10))&lt;br /&gt;    Log(&amp;quot;1Gwei - 1Gwei : &amp;quot;, (BigInt(oneGwei) - BigInt(oneGweiForHex)).toString(10))&lt;br /&gt;    Log(&amp;quot;1Gwei + 1Gwei : &amp;quot;, (BigInt(oneGwei) + BigInt(oneGweiForHex)).toString(10))&lt;br /&gt;    Log(&amp;quot;(1Gwei + 1) % 1Gwei : &amp;quot;, (BigInt(oneGwei + 1) % BigInt(oneGweiForHex)).toString(10))&lt;br /&gt;    Log(&amp;quot;1Gwei ** 2 : &amp;quot;, (BigInt(oneGwei) ** BigInt(2)).toString(10))&lt;br /&gt;    Log(&amp;quot;The square root of 100 : &amp;quot;, (BigInt(100) ** BigFloat(0.5)).toString(10))&lt;br /&gt;&lt;br /&gt;    Log(&amp;quot;Number.MAX_SAFE_INTEGER : &amp;quot;, BigInt(Number.MAX_SAFE_INTEGER).toString(10))&lt;br /&gt;    Log(&amp;quot;Number.MAX_SAFE_INTEGER * 2 : &amp;quot;, (BigInt(Number.MAX_SAFE_INTEGER) * BigInt(&amp;quot;2&amp;quot;)).toString(10))&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Debugging tool testing:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-08 11:39:50		Info	Number.MAX_SAFE_INTEGER * 2 : 18014398509481982&lt;br /&gt;2023-06-08 11:39:50		Info	Number.MAX_SAFE_INTEGER : 9007199254740991&lt;br /&gt;2023-06-08 11:39:50		Info	The square root of 100 : 10&lt;br /&gt;2023-06-08 11:39:50		Info	1Gwei ** 2 : 1000000000000000000&lt;br /&gt;2023-06-08 11:39:50		Info	(1Gwei + 1) % 1Gwei : 1&lt;br /&gt;2023-06-08 11:39:50		Info	1Gwei + 1Gwei : 2000000000&lt;br /&gt;2023-06-08 11:39:50		Info	1Gwei - 1Gwei : 0&lt;br /&gt;2023-06-08 11:39:50		Info	1Gwei * 1Gwei : 1000000000000000000&lt;br /&gt;2023-06-08 11:39:50		Info	1Gwei / 1Gwei : 1&lt;br /&gt;2023-06-08 11:39:50		Info	oneGweiForHex : 0x3b9aca00&lt;br /&gt;2023-06-08 11:39:50		Info	oneGwei : 1000000000&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;### BigFloat&lt;br /&gt;&lt;br /&gt;The ```BigFloat``` object is used similarly to the ```BigInt``` object to represent floating point numbers with larger values, and it also supports addition, subtraction, multiplication and division.&lt;br /&gt;The ```BigFloat``` object supports the ```toFixed()``` method.&lt;br /&gt;&lt;br /&gt;Refer to the following code example:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    var pi = 3.14&lt;br /&gt;    var oneGwei = &amp;quot;1000000000&amp;quot;&lt;br /&gt;    var oneGweiForHex = &amp;quot;0x3b9aca00&amp;quot;&lt;br /&gt;&lt;br /&gt;    Log(&amp;quot;pi + oneGwei : &amp;quot;, (BigFloat(pi) + BigFloat(oneGwei)).toFixed(2))&lt;br /&gt;    Log(&amp;quot;pi - oneGweiForHex : &amp;quot;, (BigFloat(pi) - BigFloat(oneGweiForHex)).toFixed(2))&lt;br /&gt;    Log(&amp;quot;pi * 2.0 : &amp;quot;, (BigFloat(pi) * BigFloat(2.0)).toFixed(2))&lt;br /&gt;    Log(&amp;quot;pi / 2.0 : &amp;quot;, (BigFloat(pi) / BigFloat(2.0)).toFixed(2))&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Debugging tool testing:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;2023-06-08 13:56:44		Info	pi / 2.0 : 1.57&lt;br /&gt;2023-06-08 13:56:44		Info	pi * 2.0 : 6.28&lt;br /&gt;2023-06-08 13:56:44		Info	pi - oneGweiForHex : -999999996.86&lt;br /&gt;2023-06-08 13:56:44		Info	pi + oneGwei : 1000000003.14&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;### BigDecimal&lt;br /&gt;&lt;br /&gt;The ```BigDecimal``` object is compatible with integer values and floating point values, and supports initialization with the ```BigInt``` object and the ```BigFloat``` object, and it also supports addition, subtraction, multiplication and division.&lt;br /&gt;&lt;br /&gt;Refer to the following code example:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    var pi = 3.1415&lt;br /&gt;    var oneGwei = 1000000000&lt;br /&gt;    var oneGweiForHex = &amp;quot;0x3b9aca00&amp;quot;&lt;br /&gt;&lt;br /&gt;    Log(&amp;quot;pi : &amp;quot;, BigDecimal(pi).toFixed(2))&lt;br /&gt;    Log(&amp;quot;oneGwei : &amp;quot;, BigDecimal(oneGwei).toString())&lt;br /&gt;    Log(&amp;quot;oneGweiForHex : &amp;quot;, BigDecimal(BigInt(oneGweiForHex)).toString())&lt;br /&gt;&lt;br /&gt;    Log(&amp;quot;BigInt(oneGwei) : &amp;quot;, BigDecimal(BigInt(oneGwei)).toString())    &lt;br /&gt;    Log(&amp;quot;BigFloat(pi) : &amp;quot;, BigDecimal(BigFloat(pi)).toFixed(4))&lt;br /&gt;&lt;br /&gt;    Log(&amp;quot;oneGwei + pi : &amp;quot;, (BigDecimal(oneGwei) + BigDecimal(pi)).toString())&lt;br /&gt;    Log(&amp;quot;oneGwei - pi : &amp;quot;, (BigDecimal(oneGwei) - BigDecimal(pi)).toString())&lt;br /&gt;    Log(&amp;quot;2.0 * pi : &amp;quot;, (BigDecimal(2.0) * BigDecimal(pi)).toString())&lt;br /&gt;    Log(&amp;quot;pi / pi : &amp;quot;, (BigDecimal(pi) / BigDecimal(pi)).toString())&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Running in the debugging tool:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-08 14:52:53		Info	pi / pi : 1&lt;br /&gt;2023-06-08 14:52:53		Info	2.0 * pi : 6.283&lt;br /&gt;2023-06-08 14:52:53		Info	oneGwei - pi : 999999996.8585&lt;br /&gt;2023-06-08 14:52:53		Info	oneGwei + pi : 1000000003.1415&lt;br /&gt;2023-06-08 14:52:53		Info	BigFloat(pi) : 3.1415&lt;br /&gt;2023-06-08 14:52:53		Info	BigInt(oneGwei) : 1e+9&lt;br /&gt;2023-06-08 14:52:53		Info	oneGweiForHex : 1e+9&lt;br /&gt;2023-06-08 14:52:53		Info	oneGwei : 1e+9&lt;br /&gt;2023-06-08 14:52:53		Info	pi : 3.14&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;### Unit conversions&lt;br /&gt;&lt;br /&gt;The following two functions: ```toAmount()```, ```toInnerAmount()``` we have used many times in previous courses, these two functions are mainly used for data precision conversion.&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function toAmount(s, decimals) {&lt;br /&gt;    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function toInnerAmount(n, decimals) {&lt;br /&gt;    return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;The ```toAmount()``` function converts (reduces) a variable ```s``` according to the precision parameter ```decimals```. In web3 practical development, it is often necessary to deal with some chained hexadecimal data.&lt;br /&gt;We have often encountered this in our previous courses, for example, the ```data``` field data in the ```Transfer(address,address,uint256)``` event of a smart contract:&lt;br /&gt;&lt;br /&gt;```desc&lt;br /&gt;{&lt;br /&gt;	&amp;quot;data&amp;quot;: &amp;quot;0x00000000000000000000000000000000000000000000000001c1a55000000000&amp;quot;,&lt;br /&gt;	&amp;quot;topics&amp;quot;: [&amp;quot;0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef&amp;quot;, &amp;quot;0x0000000000000000000000006b75d8af000000e20b7a7ddf000ba900b4009a80&amp;quot;, &amp;quot;0x000000000000000000000000bcb095c1f9c3dc02e834976706c87dee5d0f1fb6&amp;quot;],&lt;br /&gt;	&amp;quot;transactionHash&amp;quot;: &amp;quot;0x27f9bf5abe3148169b4b85a83e1de32bd50eb81ecc52e5af006157d93353e4c4&amp;quot;,&lt;br /&gt;	&amp;quot;transactionIndex&amp;quot;: &amp;quot;0x0&amp;quot;,&lt;br /&gt;	&amp;quot;removed&amp;quot;: false,&lt;br /&gt;	&amp;quot;address&amp;quot;: &amp;quot;0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&amp;quot;,&lt;br /&gt;	&amp;quot;blockHash&amp;quot;: &amp;quot;0x847be24a7b159c292bda030a011dfec89487b70e71eed486969b032d6ef04bad&amp;quot;,&lt;br /&gt;	&amp;quot;blockNumber&amp;quot;: &amp;quot;0x109b1cc&amp;quot;,&lt;br /&gt;	&amp;quot;logIndex&amp;quot;: &amp;quot;0x0&amp;quot;&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;When processing data ```&amp;quot;data&amp;quot;: &amp;quot;0x00000000000000000000000000000000000000000000000001c1a55000000000&amp;quot;```, we use the ```toAmount()``` function. This processing is designed to do a good job of converting data field data to readable values.&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function toAmount(s, decimals) {&lt;br /&gt;    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function main() {&lt;br /&gt;    var data = &amp;quot;0x00000000000000000000000000000000000000000000000001c1a55000000000&amp;quot;&lt;br /&gt;    Log(toAmount(data, 18))  // Print out 0.12656402755905127&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;1 ETH token, as we know, is ```1e18 wei```, if we get a data ```126564027559051260``` in ```wei```, how to convert it to ETH tokens?&lt;br /&gt;Using the ```toAmount(, 18)``` function is a very simple conversion method. The ```toInnerAmount()``` function is the reverse operation of the ```toAmount()``` function (depending on the precision, zoom in), and it is easy to convert the data using these two functions.&lt;br /&gt;&lt;br /&gt;It is important to note the integer value safety range in the JavaScript language, ```Number.MAX_SAFE_INTEGER```, and the following example illustrates a hidden problem when converting data:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function toAmount(s, decimals) {&lt;br /&gt;    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())&lt;br /&gt;}&lt;br /&gt;function toInnerAmount(n, decimals) {&lt;br /&gt;    return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)&lt;br /&gt;}&lt;br /&gt;function main() {&lt;br /&gt;    var amount = 0.01&lt;br /&gt;    var innerAmount = Number(toInnerAmount(amount, 18))       &lt;br /&gt;&lt;br /&gt;    Log(&amp;quot;Number.MAX_SAFE_INTEGER:&amp;quot;, Number.MAX_SAFE_INTEGER)  // 9007199254740991&lt;br /&gt;    Log(&amp;quot;innerAmount:&amp;quot;, innerAmount)                          // 10000000000000000&lt;br /&gt;&lt;br /&gt;    Log(&amp;quot;typeof(innerAmount):&amp;quot;, typeof(innerAmount), &amp;quot;, innerAmount:&amp;quot;, innerAmount)&lt;br /&gt;    &lt;br /&gt;    // Decimal value 10000000000000000 -&amp;gt; Hexadecimal value 0x2386f26fc10000&lt;br /&gt;    Log(&amp;quot;Convert&amp;quot;, innerAmount, &amp;quot;to hexadecimal:&amp;quot;, innerAmount.toString(16))&lt;br /&gt;    Log(&amp;quot;Convert&amp;quot;, BigInt(10000000000000000).toString(10), &amp;quot;to hexadecimal:&amp;quot;, BigInt(10000000000000000).toString(16))&lt;br /&gt;    &lt;br /&gt;    Log(&amp;quot;0x&amp;quot; + BigInt(10000000000000000).toString(16), &amp;quot;Convert to decimal:&amp;quot;, toAmount(&amp;quot;0x&amp;quot; + BigInt(10000000000000000).toString(16), 0))&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;It is possible to run in the debugging tool:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-15 16:21:40		Info	Convert 0x2386f26fc10000 to decimal: 10000000000000000&lt;br /&gt;2023-06-15 16:21:40		Info	Convert 10000000000000000 to hexadecimal: 2386f26fc10000&lt;br /&gt;2023-06-15 16:21:40		Info	Convert 10000000000000000 to hexadecimal: 10000000000000000&lt;br /&gt;2023-06-15 16:21:40		Info	typeof(innerAmount): number , innerAmount: 10000000000000000&lt;br /&gt;2023-06-15 16:21:40		Info	innerAmount: 10000000000000000&lt;br /&gt;2023-06-15 16:21:40		Info	Number.MAX_SAFE_INTEGER: 9007199254740991&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Through observation we found that:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;Log(&amp;quot;Convert&amp;quot;, innerAmount, &amp;quot;to hexadecimal:&amp;quot;, innerAmount.toString(16))&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;This line of code corresponds to the log output: ```Converting 10000000000000000 to hex: 10000000000000000```, which is not converted correctly. The reason is naturally that 10000000000000000 is beyond ```Number.MAX_SAFE_INTEGER```.&lt;br /&gt;&lt;br /&gt;But when the decimal value is within the safe range, i.e., less than ```Number.MAX_SAFE_INTEGER```, the ```toString(16)``` function converts it properly again, for example:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    var value = 1000&lt;br /&gt;    Log(&amp;quot;Convert value to hexadecimal:&amp;quot;, &amp;quot;0x&amp;quot; + value.toString(16))   // 0x3e8&lt;br /&gt;    Log(&amp;quot;Convert 0x3e8 to decimal:&amp;quot;, Number(&amp;quot;0x3e8&amp;quot;))               // 1000&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;In blockchain, even ```0.01``` ETH converted to a value of ```10000000000000000``` in ```wei``` will exceed ```Number.MAX_SAFE_INTEGER``, so a safer conversion for such cases is: ```BigInt(10000000000000000).toString(16)```.&lt;br /&gt;&lt;br /&gt;## Simulation Calls&lt;br /&gt;&lt;br /&gt;Executing transactions and calling the ```Write``` method of smart contracts on Ethereum costs a certain amount of gas and sometimes it fails. It is important to know which transactions are likely to fail before sending them and calling them. There are simulated calls on Ethereum for testing.&lt;br /&gt;&lt;br /&gt;### eth_call&lt;br /&gt;&lt;br /&gt;Ethereum&amp;#39;s RPC method ```eth_call```: it can simulate a transaction and return the result of a possible transaction, but it does not actually execute the transaction on the blockchain.&lt;br /&gt;&lt;br /&gt;The ```eth_call``` method has 2 parameters, the first one is a dictionary structure, ```transactionObject```:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;// transactionObject&lt;br /&gt;{&lt;br /&gt;    &amp;quot;from&amp;quot; : ...,     // The address from which the transaction is sent&lt;br /&gt;    &amp;quot;to&amp;quot; : ...,       // The address to which the transaction is addressed&lt;br /&gt;    &amp;quot;gas&amp;quot; : ...,      // The integer of gas provided for the transaction execution&lt;br /&gt;    &amp;quot;gasPrice&amp;quot; : ..., // The integer of gasPrice used for each paid gas encoded as hexadecimal&lt;br /&gt;    &amp;quot;value&amp;quot; : ...,    // The integer of value sent with this transaction encoded as hexadecimal&lt;br /&gt;    &amp;quot;data&amp;quot; : ...,     // The hash of the method signature and encoded parameters. For more information, see the Contract ABI description in the Solidity documentation&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;The second parameter is ```blockNumber```: you can pass the label ```latest/pending/earliest```, etc:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;/* blockNumber&lt;br /&gt;The block number in hexadecimal format or the string latest, earliest, pending, safe or &lt;br /&gt;finalized (safe and finalized tags are only supported on Ethereum, Gnosis, Arbitrum, &lt;br /&gt;Arbitrum Nova and Avalanche C-chain), see the default block parameter description in &lt;br /&gt;the official Ethereum documentation&lt;br /&gt;*/&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Next, we take the smart contract method ```approve``` and ```transfer``` calls of the token ```DAI``` as an example for simulation calls, and the following test environment is the main Ethereum network.&lt;br /&gt;&lt;br /&gt;### Simulation call approve&lt;br /&gt;&lt;br /&gt;We are all familiar with the ```approve``` method for ERC20 contracts, and we have practiced it in previous courses. Since the ERC20 contract is already built into the FMZ platform ABI, there is no need to register the ABI of the smart contract to be called by the simulation.&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    var contractAddressUniswapV3SwapRouterV2 = &amp;quot;0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45&amp;quot;&lt;br /&gt;    var contractAddress_DAI = &amp;quot;0x6b175474e89094c44da98b954eedeac495271d0f&amp;quot;&lt;br /&gt;    var wallet = exchange.IO(&amp;quot;address&amp;quot;)&lt;br /&gt;&lt;br /&gt;    // encode approve&lt;br /&gt;    var data = exchange.IO(&amp;quot;encode&amp;quot;, contractAddress_DAI, &amp;quot;approve(address,uint256)&amp;quot;, &lt;br /&gt;        contractAddressUniswapV3SwapRouterV2, &amp;quot;0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&amp;quot;)&lt;br /&gt;    Log(&amp;quot;ERC20 token DAI approve encode, data:&amp;quot;, data)&lt;br /&gt;    &lt;br /&gt;    var transactionObject = {&lt;br /&gt;        &amp;quot;from&amp;quot; : wallet,&lt;br /&gt;        &amp;quot;to&amp;quot; : contractAddress_DAI,&lt;br /&gt;        // &amp;quot;gasPrice&amp;quot; : &amp;quot;0x&amp;quot; + parseInt(&amp;quot;21270894680&amp;quot;).toString(16),&lt;br /&gt;        // &amp;quot;gas&amp;quot; : &amp;quot;0x&amp;quot; + parseInt(&amp;quot;21000&amp;quot;).toString(16),&lt;br /&gt;        &amp;quot;data&amp;quot; : &amp;quot;0x&amp;quot; + data,&lt;br /&gt;    }&lt;br /&gt;    var blockNumber = &amp;quot;latest&amp;quot;&lt;br /&gt;    &lt;br /&gt;    var ret = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_call&amp;quot;, transactionObject, blockNumber)&lt;br /&gt;    Log(&amp;quot;ret:&amp;quot;, ret)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;The code in the example first encodes the ```approve(address,uint256)``` method and parameters, and the parameter value ```0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff``` of the ```approve``` method indicates the maximum number of authorizations. Authorization is given to the smart contract at address ```0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45``` i.e. the router contract for ```Uniswap V3```. Finally the Ethereum RPC method ```eth_call``` is called for simulation. You can see that the ```gasPrice``` and ```gas``` fields in the ```transactionObject``` parameters can be omitted.&lt;br /&gt;&lt;br /&gt;The debugging tool is run and the simulation calls the approve method to authorize successfully (it does not authorize actually):&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-09 11:58:39		Info	ret: 0x0000000000000000000000000000000000000000000000000000000000000001&lt;br /&gt;2023-06-09 11:58:39		Info	ERC20 token DAI approve encode, data: 095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;It is also possible to simulate some failure scenarios, when we adjust the ```gasPrice``` and ```gas``` parameters, if the ETH in the wallet is not enough to pay the gas fee, an error will be reported::&lt;br /&gt;&lt;br /&gt;&amp;gt; insufficient funds&lt;br /&gt;&lt;br /&gt;When the gas cost is set too low, an error will be reported:&lt;br /&gt;&lt;br /&gt;&amp;gt; intrinsic gas too low: have 21000, want 21944 (supplied gas 21000)&lt;br /&gt;&lt;br /&gt;### Simulation call transfer&lt;br /&gt;&lt;br /&gt;We are familiar with ERC20&amp;#39;s ```transfer``` method, which allows you to transfer ERC20 tokens to a certain wallet address, so let&amp;#39;s try to simulate a transfer of 1000 DAI to Vitalik Buterin.&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function toInnerAmount(n, decimals) {&lt;br /&gt;    return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)&lt;br /&gt;}&lt;br /&gt;function main() {&lt;br /&gt;    var walletVitalik = &amp;quot;0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&amp;quot;&lt;br /&gt;    var contractAddress_DAI = &amp;quot;0x6b175474e89094c44da98b954eedeac495271d0f&amp;quot;&lt;br /&gt;    var wallet = exchange.IO(&amp;quot;address&amp;quot;)&lt;br /&gt;&lt;br /&gt;    // transfer to Vitalik Buterin&lt;br /&gt;    var decimals_DAI = exchange.IO(&amp;quot;api&amp;quot;, contractAddress_DAI, &amp;quot;decimals&amp;quot;)&lt;br /&gt;    var transferAmount = toInnerAmount(1000, decimals_DAI)&lt;br /&gt;    Log(&amp;quot;Transfer amount:&amp;quot;, 1000, &amp;quot;DAI, use toInnerAmount convert to:&amp;quot;, transferAmount)&lt;br /&gt;&lt;br /&gt;    // encode transfer&lt;br /&gt;    var data = exchange.IO(&amp;quot;encode&amp;quot;, contractAddress_DAI, &amp;quot;transfer(address,uint256)&amp;quot;,&lt;br /&gt;        walletVitalik, transferAmount)&lt;br /&gt;&lt;br /&gt;    var transactionObject = {&lt;br /&gt;        &amp;quot;from&amp;quot; : wallet,&lt;br /&gt;        &amp;quot;to&amp;quot; : contractAddress_DAI,&lt;br /&gt;        &amp;quot;data&amp;quot; : &amp;quot;0x&amp;quot; + data,&lt;br /&gt;    }&lt;br /&gt;    var blockNumber = &amp;quot;latest&amp;quot;&lt;br /&gt;    &lt;br /&gt;    var ret = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_call&amp;quot;, transactionObject, blockNumber)&lt;br /&gt;    return ret &lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Since I don&amp;#39;t have DAI tokens in this test wallet, running it in the debug tool reported the following error unexpectedly:&lt;br /&gt;&lt;br /&gt;&amp;gt; execution reverted: Dai/insufficient-balance&lt;br /&gt;&lt;br /&gt;Check the wallet address of Vitalik Buterin: ```0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045```, it is clear that this wallet has DAI tokens. So let&amp;#39;s adjust the transfer direction of the simulation call and simulate the transfer of 1000 DAI from Vitalik Buterin to us.&lt;br /&gt;&lt;br /&gt;Modify the code, where the changes I made comments:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function toInnerAmount(n, decimals) {&lt;br /&gt;    return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)&lt;br /&gt;}&lt;br /&gt;function main() {&lt;br /&gt;    var walletVitalik = &amp;quot;0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&amp;quot;&lt;br /&gt;    var contractAddress_DAI = &amp;quot;0x6b175474e89094c44da98b954eedeac495271d0f&amp;quot;&lt;br /&gt;    var wallet = exchange.IO(&amp;quot;address&amp;quot;)&lt;br /&gt;&lt;br /&gt;    var decimals_DAI = exchange.IO(&amp;quot;api&amp;quot;, contractAddress_DAI, &amp;quot;decimals&amp;quot;)&lt;br /&gt;    var transferAmount = toInnerAmount(1000, decimals_DAI)&lt;br /&gt;    Log(&amp;quot;Transfer amount:&amp;quot;, 1000, &amp;quot;DAI, use toInnerAmount convert to:&amp;quot;, transferAmount)&lt;br /&gt;&lt;br /&gt;    // encode transfer&lt;br /&gt;    var data = exchange.IO(&amp;quot;encode&amp;quot;, contractAddress_DAI, &amp;quot;transfer(address,uint256)&amp;quot;,&lt;br /&gt;        wallet, transferAmount)     // Use the wallet variable as a parameter and change the transfer recipient&amp;#39;s address to my own&lt;br /&gt;&lt;br /&gt;    var transactionObject = {&lt;br /&gt;        &amp;quot;from&amp;quot; : walletVitalik,     // Use the walletVitalik variable as the value of the from field to simulate that the call was made from the Vitalik Buterin&amp;#39;s wallet address&lt;br /&gt;        &amp;quot;to&amp;quot; : contractAddress_DAI,&lt;br /&gt;        &amp;quot;data&amp;quot; : &amp;quot;0x&amp;quot; + data,&lt;br /&gt;    }&lt;br /&gt;    var blockNumber = &amp;quot;latest&amp;quot;&lt;br /&gt;    &lt;br /&gt;    var ret = exchange.IO(&amp;quot;api&amp;quot;, &amp;quot;eth&amp;quot;, &amp;quot;eth_call&amp;quot;, transactionObject, blockNumber)&lt;br /&gt;    Log(ret)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Debugging tool test:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;2023-06-09 13:34:31		Info	0x0000000000000000000000000000000000000000000000000000000000000001&lt;br /&gt;2023-06-09 13:34:31		Info	Transfer amount: 1000 DAI, use toInnerAmount convert to: 1000000000000000000000&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Using the FMZ Quant Trading Platform, it is easy to simulate the results of transactions and avoid unnecessary loss of gas fees from sending potentially failed transactions. We used the example code from this chapter of the course to simulate the call to transfer money to Vitalik Buterin&amp;#39;s wallet and Vitalik Buterin&amp;#39;s wallet to transfer money to us. Of course, there are many more uses for this ```eth_call``` method. Use your imagination, what would you use the ```eth_call``` method for?&lt;br /&gt;&lt;br /&gt;## Identify ERC721 Contracts&lt;br /&gt;&lt;br /&gt;We know that tokens like ETH and BTC are homogenized tokens, and the token in your wallet is not different from the token in my wallet. But there are many things in the world that are not homogeneous, such as real estate, antiques, virtual artwork, etc. These cannot be represented by homogeneous tokens in abstraction. Therefore, there is the ERC721 standard to abstract non-homogeneous objects, and there is NFT and related concepts.&lt;br /&gt;So among the many smart contracts deployed on Ethereum, how do we identify which smart contracts are ERC721 standard smart contracts?&lt;br /&gt;&lt;br /&gt;To identify ERC721, it is important to know the ERC165 standard first.&lt;br /&gt;&lt;br /&gt;### ERC165&lt;br /&gt;With the ERC165 standard, a smart contract can declare the interfaces it supports for other contracts to check. An ERC165 interface contract has only one function: ```supportsInterface(bytes4 interfaceId)```, the parameter ```interfaceId``` is the interface Id to be queried. If the contract implements the interfaceId returns a boolean true value, otherwise it returns a false value.&lt;br /&gt;&lt;br /&gt;Here we are going to talk about how this ```interfaceId``` is calculated and encoded specifically.&lt;br /&gt;&lt;br /&gt;[ERC165 Standard](https://eips.ethereum.org/EIPS/eip-165) shows an example:&lt;br /&gt;&lt;br /&gt;```solidity&lt;br /&gt;pragma solidity ^0.4.20;&lt;br /&gt;&lt;br /&gt;interface Solidity101 {&lt;br /&gt;    function hello() external pure;&lt;br /&gt;    function world(int) external pure;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;contract Selector {&lt;br /&gt;    function calculateSelector() public pure returns (bytes4) {&lt;br /&gt;        Solidity101 i;&lt;br /&gt;        return i.hello.selector ^ i.world.selector;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;For the function signature of the interface (consisting of a function name and a list of parameter types) to perform a dissimilarity operation, for an ERC165 interface contract where the contract has only one function:&lt;br /&gt;&lt;br /&gt;```solidity&lt;br /&gt;pragma solidity ^0.4.20;&lt;br /&gt;&lt;br /&gt;interface ERC165 {&lt;br /&gt;    /// @notice Query if a contract implements an interface&lt;br /&gt;    /// @param interfaceID The interface identifier, as specified in ERC-165&lt;br /&gt;    /// @dev Interface identification is specified in ERC-165. This function&lt;br /&gt;    ///  uses less than 30,000 gas.&lt;br /&gt;    /// @return `true` if the contract implements `interfaceID` and&lt;br /&gt;    ///  `interfaceID` is not 0xffffffff, `false` otherwise&lt;br /&gt;    function supportsInterface(bytes4 interfaceID) external view returns (bool);&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;&amp;gt; The interface identifier for this interface is 0x01ffc9a7. You can calculate this by running bytes4(keccak256(&amp;#39;supportsInterface(bytes4)&amp;#39;)); or using the Selector contract above.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Calculate the function signature directly and take its first 4 bytes to arrive at ```interfaceId```.&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    var ret = Encode(&amp;quot;keccak256&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;hex&amp;quot;, &amp;quot;supportsInterface(bytes4)&amp;quot;)&lt;br /&gt;    Log(&amp;quot;supportsInterface(bytes4) interfaceId:&amp;quot;, &amp;quot;0x&amp;quot; + ret.slice(0, 8))&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Tests can be run in the debug tool at:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-13 14:53:35		Info	supportsInterface(bytes4) interfaceId: 0x01ffc9a7&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;It can be seen that the calculated results are consistent with the description in the [ERC165 Standard](https://eips.ethereum.org/EIPS/eip-165) document.&lt;br /&gt;&lt;br /&gt;### ERC721&lt;br /&gt;&lt;br /&gt;Next let&amp;#39;s look at the interface definition of the ERC721 contract standard:&lt;br /&gt;&lt;br /&gt;```solidity&lt;br /&gt;interface ERC721 /* is ERC165 */ {&lt;br /&gt;    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);&lt;br /&gt;&lt;br /&gt;    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);&lt;br /&gt;&lt;br /&gt;    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);&lt;br /&gt;&lt;br /&gt;    function balanceOf(address _owner) external view returns (uint256);&lt;br /&gt;&lt;br /&gt;    function ownerOf(uint256 _tokenId) external view returns (address);&lt;br /&gt;&lt;br /&gt;    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;&lt;br /&gt;&lt;br /&gt;    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;&lt;br /&gt;&lt;br /&gt;    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;&lt;br /&gt;&lt;br /&gt;    function approve(address _approved, uint256 _tokenId) external payable;&lt;br /&gt;&lt;br /&gt;    function setApprovalForAll(address _operator, bool _approved) external;&lt;br /&gt;&lt;br /&gt;    function getApproved(uint256 _tokenId) external view returns (address);&lt;br /&gt;&lt;br /&gt;    function isApprovedForAll(address _owner, address _operator) external view returns (bool);&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;If we want to determine whether a smart contract is an ERC721 contract, first we need to know the ```interfaceId``` of the ERC721 contract before we can try to use the ```supportsInterface(bytes4 interfaceId)``` method to determine it. In previous courses, we have familiarized us with some concepts of the ERC165 standard and the algorithm for calculating the ```interfaceId```, and we write code to calculate directly:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function calcSelector(arrSelector) {&lt;br /&gt;    var ret = null&lt;br /&gt;    if (Array.isArray(arrSelector)) {&lt;br /&gt;        if (arrSelector.length == 1) {&lt;br /&gt;            ret = Encode(&amp;quot;keccak256&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;hex&amp;quot;, arrSelector[0])&lt;br /&gt;        } else if (arrSelector.length == 0) {&lt;br /&gt;            throw &amp;quot;Error: the number of elements in the array is 0&amp;quot;&lt;br /&gt;        } else {&lt;br /&gt;            var viewEncodeData = null&lt;br /&gt;            for (var i = 0; i &amp;lt; arrSelector.length; i++) {&lt;br /&gt;                if (i == 0) {&lt;br /&gt;                    ret = new Uint8Array(Encode(&amp;quot;keccak256&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;raw&amp;quot;, arrSelector[i]))&lt;br /&gt;                } else {&lt;br /&gt;                    viewData = new Uint8Array(Encode(&amp;quot;keccak256&amp;quot;, &amp;quot;string&amp;quot;, &amp;quot;raw&amp;quot;, arrSelector[i]))&lt;br /&gt;                    &lt;br /&gt;                    if (viewData.length != ret.length) {&lt;br /&gt;                        throw &amp;quot;Error: TypeArray view length is different&amp;quot;&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    for (var index = 0; index &amp;lt; ret.length; index++) {&lt;br /&gt;                        ret[index] ^= viewData[index]&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            ret = Encode(&amp;quot;raw&amp;quot;, &amp;quot;raw&amp;quot;, &amp;quot;hex&amp;quot;, ret.buffer)&lt;br /&gt;        }&lt;br /&gt;    } else {&lt;br /&gt;        throw &amp;quot;Error: The parameter requires an array type.&amp;quot;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return &amp;quot;0x&amp;quot; + ret.slice(0, 8)&lt;br /&gt;}&lt;br /&gt;function main() {&lt;br /&gt;    // supportsInterface(bytes4): 0x01ffc9a7&lt;br /&gt;    // var ret = calcSelector([&amp;quot;supportsInterface(bytes4)&amp;quot;])&lt;br /&gt;&lt;br /&gt;    // ERC721Metadata: 0x5b5e139f&lt;br /&gt;    /* &lt;br /&gt;    var arrSelector = [&lt;br /&gt;        &amp;quot;name()&amp;quot;,&lt;br /&gt;        &amp;quot;symbol()&amp;quot;,&lt;br /&gt;        &amp;quot;tokenURI(uint256)&amp;quot;&lt;br /&gt;    ]&lt;br /&gt;    var ret = calcSelector(arrSelector)&lt;br /&gt;    */&lt;br /&gt;&lt;br /&gt;    // ERC721: 0x80ac58cd&lt;br /&gt;    // /*&lt;br /&gt;    var arrSelector = [&lt;br /&gt;        &amp;quot;balanceOf(address)&amp;quot;,&lt;br /&gt;        &amp;quot;ownerOf(uint256)&amp;quot;,&lt;br /&gt;        &amp;quot;safeTransferFrom(address,address,uint256,bytes)&amp;quot;,&lt;br /&gt;        &amp;quot;safeTransferFrom(address,address,uint256)&amp;quot;,&lt;br /&gt;        &amp;quot;transferFrom(address,address,uint256)&amp;quot;,&lt;br /&gt;        &amp;quot;approve(address,uint256)&amp;quot;,&lt;br /&gt;        &amp;quot;setApprovalForAll(address,bool)&amp;quot;,&lt;br /&gt;        &amp;quot;getApproved(uint256)&amp;quot;,&lt;br /&gt;        &amp;quot;isApprovedForAll(address,address)&amp;quot;,&lt;br /&gt;    ]&lt;br /&gt;    var ret = calcSelector(arrSelector)&lt;br /&gt;    // */&lt;br /&gt;&lt;br /&gt;    Log(ret)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;The code uses the ```Encode()``` function for function signature calculation (the ```keccak256``` algorithm), and for the calculation in the code example above, specifying the output parameter of the ```Encode()``` function as ```&amp;quot;raw&amp;quot;```, the function returns the ```ArrayBuffer``` type of ```JavaScript``` language.&lt;br /&gt;To perform a ```^``` (iso-or) operation on two ```ArrayBuffer``` objects, you need to create a ```TypedArray``` view based on the ```ArrayBuffer``` object, then iterate through the data in it and perform the iso-or operation one by one.&lt;br /&gt;&lt;br /&gt;Run in the debugging tool:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-13 15:04:09		Info	0x80ac58cd&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;It can be seen that the calculated results are consistent with those described in [eip-721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md).&lt;br /&gt;&lt;br /&gt;```solidity&lt;br /&gt;pragma solidity ^0.4.20;&lt;br /&gt;&lt;br /&gt;/// @title ERC-721 Non-Fungible Token Standard/// @dev See &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAB2KlHRoXVxIU2AJR3lo1zQ8J7vOTcUmTEyErNTCYa3eZjL8pYqOzBfIhhm6tihYVE" title="https://eips.ethereum.org/EIPS/eip-721/// "&gt;https://eips.ethereum.org/EIPS/eip-721/// &lt;/a&gt; Note: the ERC-165 identifier for this interface is 0x80ac58cd.interface ERC721 /* is ERC165 */ {&lt;br /&gt;    /// @dev This emits when ownership of any NFT changes by any mechanism.&lt;br /&gt;    ///  This event emits when NFTs are created (`from` == 0) and destroyed&lt;br /&gt;    ///  (`to` == 0). Exception: during contract creation, any number of NFTs&lt;br /&gt;    ///  may be created and assigned without emitting Transfer. At the time of&lt;br /&gt;    ///  any transfer, the approved address for that NFT (if any) is reset to none.&lt;br /&gt;    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;With the ERC721 interface Id, we can determine if a contract is an ERC721 standard contract or not. We use ```BAYC``` to do the test, which is a contract that follows ERC721. First we need to register the ABI, and since we only call the following three methods, we can register these three methods:&lt;br /&gt;&lt;br /&gt;- supportsInterface(interfaceId)&lt;br /&gt;- symbol()&lt;br /&gt;- name()&lt;br /&gt;&lt;br /&gt;The specific codes are as follows:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;function main() {&lt;br /&gt;    // Contract address for ERC721, BAYC is used here&lt;br /&gt;    var testContractAddress = &amp;quot;0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&amp;quot;&lt;br /&gt;&lt;br /&gt;    var testABI = `[{&lt;br /&gt;        &amp;quot;inputs&amp;quot;: [{&lt;br /&gt;            &amp;quot;internalType&amp;quot;: &amp;quot;bytes4&amp;quot;,&lt;br /&gt;            &amp;quot;name&amp;quot;: &amp;quot;interfaceId&amp;quot;,&lt;br /&gt;            &amp;quot;type&amp;quot;: &amp;quot;bytes4&amp;quot;&lt;br /&gt;        }],&lt;br /&gt;        &amp;quot;name&amp;quot;: &amp;quot;supportsInterface&amp;quot;,&lt;br /&gt;        &amp;quot;outputs&amp;quot;: [{&lt;br /&gt;            &amp;quot;internalType&amp;quot;: &amp;quot;bool&amp;quot;,&lt;br /&gt;            &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;            &amp;quot;type&amp;quot;: &amp;quot;bool&amp;quot;&lt;br /&gt;        }],&lt;br /&gt;        &amp;quot;stateMutability&amp;quot;: &amp;quot;view&amp;quot;,&lt;br /&gt;        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;&lt;br /&gt;    }, {&lt;br /&gt;        &amp;quot;inputs&amp;quot;: [],&lt;br /&gt;        &amp;quot;name&amp;quot;: &amp;quot;symbol&amp;quot;,&lt;br /&gt;        &amp;quot;outputs&amp;quot;: [{&lt;br /&gt;            &amp;quot;internalType&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;            &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;&lt;br /&gt;        }],&lt;br /&gt;        &amp;quot;stateMutability&amp;quot;: &amp;quot;view&amp;quot;,&lt;br /&gt;        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;&lt;br /&gt;    }, {&lt;br /&gt;        &amp;quot;inputs&amp;quot;: [],&lt;br /&gt;        &amp;quot;name&amp;quot;: &amp;quot;name&amp;quot;,&lt;br /&gt;        &amp;quot;outputs&amp;quot;: [{&lt;br /&gt;            &amp;quot;internalType&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;            &amp;quot;name&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;&lt;br /&gt;        }],&lt;br /&gt;        &amp;quot;stateMutability&amp;quot;: &amp;quot;view&amp;quot;,&lt;br /&gt;        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;&lt;br /&gt;    }]`&lt;br /&gt;&lt;br /&gt;    // ERC721 Interface Id, calculated in the previous course&lt;br /&gt;    var interfaceId = &amp;quot;0x80ac58cd&amp;quot;&lt;br /&gt;&lt;br /&gt;    // Register ABI&lt;br /&gt;    exchange.IO(&amp;quot;abi&amp;quot;, testContractAddress, testABI)&lt;br /&gt;&lt;br /&gt;    // Call the supportsInterface method&lt;br /&gt;    var isErc721 = exchange.IO(&amp;quot;api&amp;quot;, testContractAddress, &amp;quot;supportsInterface&amp;quot;, interfaceId)&lt;br /&gt;&lt;br /&gt;    // Output Information&lt;br /&gt;    Log(&amp;quot;Contract address:&amp;quot;, testContractAddress)&lt;br /&gt;    Log(&amp;quot;Contract name:&amp;quot;, exchange.IO(&amp;quot;api&amp;quot;, testContractAddress, &amp;quot;name&amp;quot;))&lt;br /&gt;    Log(&amp;quot;Contract code:&amp;quot;, exchange.IO(&amp;quot;api&amp;quot;, testContractAddress, &amp;quot;symbol&amp;quot;))&lt;br /&gt;    Log(&amp;quot;Whether the contract is ERC721 standard:&amp;quot;, isErc721)&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;Tests can be run in the debugging tool:&lt;br /&gt;&lt;br /&gt;```run&lt;br /&gt;2023-06-13 16:32:57		Info	Whether the contract is ERC721 standard: true&lt;br /&gt;2023-06-13 16:32:57		Info	Contract code: BAYC&lt;br /&gt;2023-06-13 16:32:57		Info	Contract name: BoredApeYachtClub&lt;br /&gt;2023-06-13 16:32:57		Info	Contract address: 0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;The contract with the address ```0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d``` is determined to be ERC721 standard.&lt;br /&gt;&lt;br /&gt;In this part, we introduced how to determine ERC721 contracts, so contracts like ERC20, which do not support the ERC165 standard, will have to be identified in another way. Do you know how to check if a contract is ERC20 standard?&lt;br /&gt;&lt;br /&gt;## Encoding calldata&lt;br /&gt;&lt;br /&gt;What is ```calldata```? By the author&amp;#39;s understanding, a simple layman&amp;#39;s description here is:&lt;br /&gt;&lt;br /&gt;&amp;gt; The &amp;quot;calldata&amp;quot; is the encoding of a function call or parameter in Ethereum, and the &amp;quot;calldata&amp;quot; is encoded according to the ABI (Application Binary Interface) specification of the contract.&lt;br /&gt;&lt;br /&gt;For example, we can encode the ```balanceOf``` and ```transfer``` method calls of the ERC20 contract we studied in the previous course, together with the parameters of the calls, into a ```calldata```. In some application scenarios, such as **interaction between contracts**, this scenario will use ```calldata```, and of course there are many other application scenarios that are not listed here.&lt;br /&gt;&lt;br /&gt;How to code a smart contract function call to get ```calldata```?&lt;br /&gt;&lt;br /&gt;In the FMZ Quant Trading Platform, you can use ```exchange.IO(&amp;quot;encode&amp;quot;, ...)``` to encode smart contract function calls, the use of exchange.IO(&amp;quot;encode&amp;quot;, ...) is very simple. The first parameter of the function is the fixed string ```&amp;quot;encode&amp;quot;```; the second parameter is the address of the smart contract; the third parameter is the name of the smart contract method to be encoded; the rest of the parameters are passed to the specific parameter value of the smart contract method to be encoded.&lt;br /&gt;&lt;br /&gt;### eth_sendRawTransaction&lt;br /&gt;&lt;br /&gt;When we encode a smart contract method call and generate the corresponding ```calldata``` data, if this smart contract method is a Write method (i.e.: write operation), we need to use the generated ```calldata``` data as the data field of the transaction and then use the Ethereum RPC method ```eth_ sendRawTransaction``` to send a request containing the raw data of that transaction to the Ethereum network.&lt;br /&gt;&lt;br /&gt;The ```eth_sendRawTransaction``` method has only one parameter, ```data```:&lt;br /&gt;&lt;br /&gt;&amp;gt; data: The signed transaction (typically signed with a library, using your private key)&lt;br /&gt;&lt;br /&gt;The ```data``` parameter is a transaction data after the signature calculation, and the transaction data structure of Ethereum has the following main fields:&lt;br /&gt;&lt;br /&gt;```javascript&lt;br /&gt;{&lt;br /&gt;    &amp;quot;nonce&amp;quot;: &amp;quot;0x1&amp;quot;,                         // Number of transactions on the account of the sender of the transaction&lt;br /&gt;    &amp;quot;gasPrice&amp;quot;: &amp;quot;0x12a05f200&amp;quot;,              // Traded Gas price&lt;br /&gt;    &amp;quot;gasLimit&amp;quot;: &amp;quot;0x5208&amp;quot;,                   // Gas limit for trading&lt;br /&gt;    &amp;quot;to&amp;quot;: &amp;quot;0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2&amp;quot;,    // Target contract address or recipient address&lt;br /&gt;    &amp;quot;value&amp;quot;: &amp;quot;0x4563918244F40000&amp;quot;,          // Number of Ethereum transferred&lt;br /&gt;    &amp;quot;data&amp;quot;: &amp;quot;0x0123456789ABCDEF&amp;quot;,           // Data to send to the contract&lt;br /&gt;}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;How to sign an Ethereum transaction?&lt;br /&gt;&lt;br /&gt;In the FMZ Quant Trading Platform, we use the ```Encode()``` function to perform the signature calculation, the specific example we write in the subsequent course &amp;quot;Execute Write method calldata&amp;quot;.&lt;br /&gt;&lt;br /&gt;To be continued...</content>
  </entry>
</feed>